ridl 2.2.5 → 2.5.5

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.
@@ -17,28 +17,52 @@ module IDL
17
17
 
18
18
  class GenFile
19
19
 
20
- @@stack = []
21
- @@cur_trans = nil
20
+ self.singleton_class.class_eval do
21
+ private
22
22
 
23
+ def _stack
24
+ @stack ||= []
25
+ end
26
+
27
+ def _start_transaction
28
+ _stack << (@transaction = [])
29
+ end
30
+
31
+ def _close_transaction
32
+ _stack.pop
33
+ @transaction = _stack.last
34
+ end
35
+
36
+ def _transaction
37
+ @transaction
38
+ end
39
+
40
+ def _commit
41
+ _transaction.reject! { |fgen| fgen.save; true }
42
+ end
43
+
44
+ def _rollback
45
+ _transaction.reject! { |fgen| fgen.remove; true } if _transaction
46
+ end
47
+
48
+ def _push(fgen)
49
+ _transaction << fgen if _transaction
50
+ end
51
+
52
+ end
23
53
  def self.transaction(&block)
24
- @@cur_trans = []
25
- @@stack << @@cur_trans
54
+ _start_transaction
26
55
  begin
27
56
  block.call if block_given?
28
- @@cur_trans.each {|fgen| fgen.save }
29
- @@cur_trans.clear
57
+ _commit
30
58
  ensure
31
- self.rollback # after successful transaction should be nothing left
32
- @@stack.pop
33
- @@cur_trans = @@stack.last
59
+ _rollback # after successful transaction should be nothing left
60
+ _close_transaction
34
61
  end
35
62
  end
36
63
 
37
64
  def self.rollback
38
- if @@cur_trans
39
- @@cur_trans.each {|fgen| fgen.remove }
40
- @@cur_trans.clear
41
- end
65
+ _rollback
42
66
  end
43
67
 
44
68
  class Content
@@ -82,8 +106,9 @@ module IDL
82
106
  :regen_marker_prefix => '//',
83
107
  :regen_marker_postfix => nil,
84
108
  :regen_marker => REGEN_MARKER_DEFAULT,
85
- :regen_keep_header => false,
86
- :output_file => nil
109
+ :regen_keep_header => true,
110
+ :output_file => nil,
111
+ :create_missing_dir => false
87
112
  }.merge(opts)
88
113
  if @options[:regenerate] && File.exists?(@fullpath)
89
114
  parse_regeneration_content
@@ -91,7 +116,7 @@ module IDL
91
116
  @content = Content.new
92
117
  end
93
118
  @fout = @options[:output_file] || Tempfile.new(@name)
94
- @@cur_trans << self
119
+ self.class.__send__(:_push, self)
95
120
  end
96
121
 
97
122
  def <<(txt)
@@ -111,11 +136,14 @@ module IDL
111
136
  "#{@options[:regen_marker_prefix]}#{@options[:regen_marker]} - HEADER_END : #{sectionid}#{@options[:regen_marker_postfix]}"
112
137
  end
113
138
 
114
- def write_regen_section(sectionid, default_content, indent = '', options = {})
139
+ def write_regen_section(sectionid, options = {})
140
+ indent = options[:indent] || ''
115
141
  self << indent << regen_start_marker(sectionid) << "\n" unless options[:header]
116
142
  if content.has_section?(sectionid)
117
143
  self << content[sectionid].join unless content[sectionid].empty?
118
- else
144
+ elsif block_given?
145
+ yield # block should yield default content
146
+ elsif default_content = options[:default_content]
119
147
  default_content = (Array === default_content) ? default_content : default_content.to_s.split("\n")
120
148
  self << (default_content.collect {|l| (s = indent.dup) << l << "\n"; s }.join) unless default_content.empty?
121
149
  end
@@ -141,22 +169,29 @@ module IDL
141
169
  # replace original
142
170
  begin
143
171
  # rename newly generated file
144
- FileUtils::mv(fgen.path, @fullpath)
172
+ FileUtils.mv(fgen.path, @fullpath)
145
173
  # preserve file mode
146
- FileUtils::chmod(File.lstat(ftmp_name).mode, @fullpath)
174
+ FileUtils.chmod(File.lstat(ftmp_name).mode, @fullpath)
147
175
  rescue
148
176
  IDL.log(0, %Q{ERROR: FAILED updating #{@path}: #{$!}})
149
177
  # restore backup
150
- FileUtils::mv(ftmp_name, @fullpath)
178
+ FileUtils.mv(ftmp_name, @fullpath)
151
179
  raise
152
180
  end
153
181
  # remove backup
154
182
  File.unlink(ftmp_name)
155
183
  else
184
+ unless File.directory?(File.dirname(@fullpath))
185
+ unless @options[:create_missing_dir]
186
+ IDL.log(0, %Q{ERROR: Cannot access output folder #{File.dirname(@fullpath)}})
187
+ exit(1)
188
+ end
189
+ FileUtils.mkdir_p(File.dirname(@fullpath))
190
+ end
156
191
  # just rename newly generated file
157
- FileUtils::mv(fgen.path, @fullpath)
192
+ FileUtils.mv(fgen.path, @fullpath)
158
193
  # set default mode for new files
159
- FileUtils::chmod(0666 - File.umask, @fullpath)
194
+ FileUtils.chmod(0666 - File.umask, @fullpath)
160
195
  end
161
196
  end
162
197
  end
@@ -115,6 +115,10 @@ module IDL::AST
115
115
  @annotations = Annotations.new
116
116
  end
117
117
 
118
+ def unescaped_name
119
+ @name.unescaped_name
120
+ end
121
+
118
122
  def parsed_name_scope
119
123
  (@enclosure ? @enclosure.parsed_name_scope : '') + '::' + @name
120
124
  end
@@ -128,7 +132,7 @@ module IDL::AST
128
132
  end
129
133
 
130
134
  def scoped_lm_name
131
- @scoped_lm_name ||= @scopes.collect{|s| s.lm_name_for_scope }.join("::").freeze
135
+ @scoped_lm_name ||= @scopes.collect{|s| s.lm_name_for_scope }.join('::').freeze
132
136
  end
133
137
 
134
138
  def marshal_dump
@@ -314,11 +318,15 @@ module IDL::AST
314
318
  end
315
319
 
316
320
  def walk_members(&block)
317
- @children.each { |c| yield(c) }
321
+ @children.each(&block)
318
322
  end
319
323
 
320
324
  def match_members(&block)
321
- !(@children.find { |c| yield(c) }).nil?
325
+ !(@children.find(&block)).nil?
326
+ end
327
+
328
+ def select_members(&block)
329
+ @children.select(&block)
322
330
  end
323
331
 
324
332
  def replace_prefix(pfx)
@@ -403,12 +411,14 @@ module IDL::AST
403
411
  IDL::AST::Union, IDL::AST::Enum, IDL::AST::Enumerator, IDL::AST::Typedef, IDL::AST::Include,
404
412
  IDL::AST::Home, IDL::AST::Porttype, IDL::AST::Component, IDL::AST::Connector
405
413
  ]
406
- attr_reader :anchor, :next
414
+ attr_reader :anchor, :next, :template, :template_params
407
415
  def initialize(_name, _enclosure, params)
408
416
  super(_name, _enclosure)
409
417
  @anchor = params[:anchor]
410
418
  @prefix = params[:prefix] || @prefix
411
419
  @not_in_repo_id = params[:not_in_repo_id]
420
+ @template = params[:template]
421
+ @template_params = (params[:template_params] || []).dup
412
422
  @next = nil
413
423
  end
414
424
 
@@ -416,6 +426,23 @@ module IDL::AST
416
426
  !@anchor.nil?
417
427
  end
418
428
 
429
+ def is_templated?
430
+ @template ? true : false
431
+ end
432
+
433
+ def template_param(param)
434
+ return nil unless @template
435
+ param = param.to_s if ::Symbol === param
436
+ if ::String === param
437
+ @template.params.each_with_index do |tp, ix|
438
+ return @template_params[ix] if tp.name == param
439
+ end
440
+ nil
441
+ else
442
+ @template_params[param] rescue nil
443
+ end
444
+ end
445
+
419
446
  def annotations
420
447
  (has_anchor? ? self.anchor : self).get_annotations
421
448
  end
@@ -452,9 +479,9 @@ module IDL::AST
452
479
  when IDL::AST::Module
453
480
  # Module reopening
454
481
  _anchor = node.has_anchor? ? node.anchor : node
455
- _anchor.annotations.concat(params[:annotations])
482
+ _anchor.annotations.concat(params.delete(:annotations))
456
483
  _last = _anchor.find_last
457
- _params = { :anchor => _anchor, :prefix => node.prefix }
484
+ _params = params.merge({ :anchor => _anchor, :prefix => node.prefix })
458
485
  _next = IDL::AST::Module.new(node.name, self, _params)
459
486
  _last.set_next(_next)
460
487
  @children << _next
@@ -685,12 +712,16 @@ module IDL::AST
685
712
  true
686
713
  end
687
714
 
688
- def instantiate(_module_instance, _concrete_params, _context = {})
715
+ def params
716
+ @template_params
717
+ end
718
+
719
+ def instantiate(_module_instance, _context = {})
689
720
  # process concrete parameters
690
721
  @template_params.each_with_index do |_tp, _ix|
691
722
  raise RuntimeError,
692
- "missing template parameter for #{typename} #{scoped_lm_name}: #{_tp.name}" unless _ix < _concrete_params.size
693
- _cp = _concrete_params[_ix]
723
+ "missing template parameter for #{typename} #{scoped_lm_name}: #{_tp.name}" unless _ix < _module_instance.template_params.size
724
+ _cp = _module_instance.template_params[_ix]
694
725
  if _cp.is_a?(IDL::Type)
695
726
  raise RuntimeError, "anonymous type definitions are not allowed!" if _cp.is_anonymous?
696
727
  # parameter should be a matching IDL::Type
@@ -772,13 +803,13 @@ module IDL::AST
772
803
  end
773
804
 
774
805
  def instantiate(_context, _enclosure)
775
- mod_inst = IDL::AST::Module.new(self.name, _enclosure, {})
776
806
  inst_params = @params.collect do |tp|
777
807
  # concrete objects are either Expression or Node; latter needs to be repacked as IDL::Type::ScopedName
778
808
  # as that is what the TemplateModule#instantiate expects
779
809
  tp.concrete.is_a?(IDL::Expression) ? tp.concrete : IDL::Type::ScopedName.new(tp.concrete)
780
810
  end
781
- @template.instantiate(mod_inst, inst_params, _context)
811
+ mod_inst = IDL::AST::Module.new(self.name, _enclosure, { :template => @template, :template_params => inst_params })
812
+ @template.instantiate(mod_inst, _context)
782
813
  mod_inst
783
814
  end
784
815
 
@@ -788,10 +819,11 @@ module IDL::AST
788
819
  end # TemplateModuleReference
789
820
 
790
821
  class Include < Module
791
- attr_reader :filename
822
+ attr_reader :filename, :fullpath
792
823
  def initialize(_name, _enclosure, params)
793
824
  super(_name, _enclosure, params)
794
825
  @filename = params[:filename]
826
+ @fullpath = params[:fullpath]
795
827
  @defined = params[:defined] || false
796
828
  @preprocessed = params[:preprocessed] || false
797
829
  #overrule
@@ -341,14 +341,14 @@ module IDL
341
341
  @options.delete(switch)
342
342
  end
343
343
 
344
- def to_option_parser(optp, idl_options)
344
+ def to_option_parser(optp, option_holder)
345
345
  @options.each do |sw, op|
346
346
  (arg_list = [sw]) << op.type
347
347
  arg_list.concat(op.description(optp.summary_indent))
348
348
  optp.on(*arg_list) do |v|
349
- op.run(v, idl_options)
349
+ op.run(v, option_holder.options)
350
350
  end
351
- optp.separator "" if op.separator
351
+ optp.separator '' if op.separator
352
352
  end
353
353
  end
354
354
 
@@ -499,7 +499,7 @@ def parse(src)
499
499
  rescue IDL::ParseError
500
500
  raise
501
501
  rescue
502
- STDERR.puts "#{$!}\n#{$!.backtrace.join("\n")}" if $VERBOSE
502
+ STDERR.puts "#{$!}\n#{$!.backtrace.join("\n")}" if IDL.verbose_level>0
503
503
  raise IDL::ParseError.new($!.message, @scanner.positions)
504
504
  end
505
505
  @d.post_parse
@@ -529,8 +529,8 @@ def is_included?(s)
529
529
  @d.is_included?(s)
530
530
  end
531
531
 
532
- def enter_include(s)
533
- @d.enter_include(s)
532
+ def enter_include(s, fp)
533
+ @d.enter_include(s, fp)
534
534
  end
535
535
 
536
536
  def leave_include()
@@ -541,8 +541,8 @@ def declare_include(s)
541
541
  @d.declare_include(s)
542
542
  end
543
543
 
544
- def define_annotation(annid, annbody)
545
- @d.define_annotation(annid, annbody)
544
+ def define_annotation(*args)
545
+ @d.define_annotation(*args)
546
546
  end
547
547
 
548
548
  def next_token
@@ -873,7 +873,7 @@ def parse(src)
873
873
  rescue IDL::ParseError
874
874
  raise
875
875
  rescue
876
- STDERR.puts "#{$!}\n#{$!.backtrace.join("\n")}" if $VERBOSE
876
+ STDERR.puts "#{$!}\n#{$!.backtrace.join("\n")}" if IDL.verbose_level>0
877
877
  raise IDL::ParseError.new($!.message, @scanner.positions)
878
878
  end
879
879
  @d.post_parse
@@ -903,8 +903,8 @@ def is_included?(s)
903
903
  @d.is_included?(s)
904
904
  end
905
905
 
906
- def enter_include(s)
907
- @d.enter_include(s)
906
+ def enter_include(s, fp)
907
+ @d.enter_include(s, fp)
908
908
  end
909
909
 
910
910
  def leave_include()
@@ -915,8 +915,8 @@ def declare_include(s)
915
915
  @d.declare_include(s)
916
916
  end
917
917
 
918
- def define_annotation(annid, annbody)
919
- @d.define_annotation(annid, annbody)
918
+ def define_annotation(*args)
919
+ @d.define_annotation(*args)
920
920
  end
921
921
 
922
922
  def next_token
@@ -17,219 +17,195 @@ require 'ridl/backend'
17
17
 
18
18
  # -----------------------------------------------------------------------
19
19
 
20
- $VERBOSE = $VERBOSE || ENV['RIDL_VERBOSE']
21
-
22
20
  module IDL
23
21
 
22
+ # TODO : LEGACY solution for R2CORBA; to be removed when R2CORBA has been updated
23
+ # See also IDL#init
24
24
  @@embedded = false unless class_variable_defined?(:@@embedded)
25
25
  @@be_name = nil unless class_variable_defined?(:@@be_name)
26
- @@preprocessing = false
27
- @@no_pidl = false
28
- @@idlstack = []
29
- @@backend = nil
30
- @@verbose_level = 0
31
26
 
32
27
  OPTIONS = {
33
28
  :outputdir => nil,
34
29
  :includepaths => [],
35
- :verbose => 0,
30
+ :xincludepaths => [],
31
+ :verbose => (ENV['RIDL_VERBOSE'] || 0).to_i,
36
32
  :debug => false,
37
33
  :namespace => nil,
38
34
  :search_incpath => false,
39
35
  :backend => nil,
40
36
  :macros => {
41
- :__RIDL__ => "#{RIDL_VERSION}",
42
- :__RIDLBE__ => nil,
43
- :__RIDLBE_VER__ => nil
37
+ :__RIDL__ => "#{RIDL_VERSION}",
38
+ :__RIDLBE__ => nil,
39
+ :__RIDLBE_VER__ => nil
44
40
  }
45
41
  }
46
42
 
47
- def IDL.preprocessing?
48
- @@preprocessing
49
- end
50
-
51
- def IDL.no_pidl?
52
- @@no_pidl
53
- end
43
+ class Engine
44
+ def initialize(backend, options)
45
+ @backend = backend ? Backend.load(backend) : Backend.null_be
46
+ @initopts = options.merge({
47
+ backend: @backend.name,
48
+ macros: options[:macros].merge({
49
+ __RIDLBE__: @backend.name.to_s,
50
+ __RIDLBE_VER__: @backend.version
51
+ })
52
+ })
53
+ @optparser = init_optparser
54
+ @inputstack = []
55
+ @options = nil
56
+ end
54
57
 
55
- def IDL.backend
56
- @@backend
57
- end
58
+ def backend
59
+ @backend
60
+ end
58
61
 
59
- def IDL.init
60
- unless @@embedded
61
- # check commandline args for explicit language mapping backend
62
- if ARGV.first =~ /^:\S+/
63
- @@be_name = ARGV.shift.reverse.chop.reverse.to_sym
64
- elsif ENV['RIDL_BE_SELECT'] # or from environment
65
- @@be_name = ENV['RIDL_BE_SELECT'].to_sym
66
- end
62
+ def options
63
+ @options || @initopts
64
+ end
67
65
 
68
- # add optional search paths for RIDL backends
69
- $:.concat(ENV['RIDL_BE_PATH'].split(/:|;/)) if ENV['RIDL_BE_PATH']
66
+ def push_input(idlfile, opts)
67
+ @inputstack << [idlfile, opts]
68
+ end
70
69
 
71
- # check for special bootstrapping switches
72
- if ARGV.first == '--preprocess'
73
- @@preprocessing = true
74
- ARGV.shift
75
- elsif ARGV.first == '--ignore-pidl'
76
- @@no_pidl = true
77
- ARGV.shift
78
- end
70
+ def pop_input
71
+ @inputstack.shift
79
72
  end
80
- # try to load the active laguage mapping backend
81
- @@backend = @@be_name ? Backend.load(@@be_name) : Backend.null_be
82
- # finalize base options
83
- OPTIONS[:preprocess] = preprocessing?
84
- OPTIONS[:ignore_pidl] = no_pidl?
85
- OPTIONS[:backend] = @@backend
86
- OPTIONS[:__RIDLBE__] = @@backend.name.to_s
87
- OPTIONS[:__RIDLBE_VER__] = @@backend.version
88
- end
89
73
 
90
- # parse commandline arguments
91
- #
92
- def IDL.parse_args
93
- script_name = File.basename($0, '.*')
94
- if not script_name =~ /ridlc/
95
- script_name = "ruby "+$0
74
+ def peek_input
75
+ @inputstack.first
96
76
  end
97
77
 
98
- # set up option parser with common options
99
- opts = OptionParser.new
100
- opts.banner = "Usage: #{script_name} [:backend] [options] [<idlfile> [<idlfile> ...]]\n\n" +
101
- " backend\t\tSpecifies the IDL language mapping backend to use.\n"+
102
- " \t\tDefault = :null\n\n"+
103
- " Active language mapping = :#{IDL.backend.name}"
104
- opts.separator ""
105
- opts.on("-I PATH", "--include=PATH", String,
106
- "Adds include searchpath.",
107
- "Default: nil") { |v| OPTIONS[:includepaths] << v }
108
- opts.on('-Dmacro=[value]', String, 'defines preprocessor macro') { |v|
109
- name, value = v.split('=')
110
- OPTIONS[:macros][name] = (value ? value : true)
111
- }
112
- opts.on("-n NAMESPACE", "--namespace=NAMESPACE", String,
113
- "Defines rootlevel enclosing namespace.",
114
- "Default: nil") { |v| OPTIONS[:namespace]=v }
115
- opts.on("-v", "--verbose",
116
- "Set verbosity level. Repeat to increment.",
117
- "Default: 0") { |v| OPTIONS[:verbose] += 1 }
118
- opts.on("--debug",
119
- "Set parser debug mode. Don't do this at home!",
120
- "Default: off") { |v| OPTIONS[:debug] = true }
121
- opts.on('--stdidl',
122
- 'Adds include path to standard IDL files provided with RIDL.',
123
- 'Default: not set') { |v|
124
- OPTIONS[:includepaths] << File.expand_path(File.join(File.dirname(__FILE__), '..', 'idl'))
125
- }
126
- opts.on("--search-includepath",
127
- "Use include paths to find main IDL source.",
128
- "Default: off") { |v| OPTIONS[:search_incpath]=v }
129
- if preprocessing?
130
- opts.on("--output=FILE", String,
131
- "Specifies filename to generate output in.",
132
- "Default: File.basename(idlfile, '.idl')+<postfix>+<ext>") { |v| OPTIONS[:output]=v }
78
+ def has_input?
79
+ !@inputstack.empty?
133
80
  end
134
81
 
135
- # setup language mapping specific options
136
- be_options = OptionList.new
137
- @@backend.setup_be(be_options, OPTIONS)
138
- be_options.to_option_parser(opts, OPTIONS)
82
+ def verbose_level
83
+ options[:verbose]
84
+ end
139
85
 
140
- opts.on('-V', "--version",
141
- "Show version information and exit.") {
142
- puts "RIDL compiler #{OPTIONS[:macros][:__RIDL__]}"
143
- puts RIDL_COPYRIGHT
144
- puts '---'
145
- @@backend.print_version
146
- exit
147
- }
86
+ def verbose_level=(l)
87
+ options[:verbose] = l
88
+ end
148
89
 
149
- opts.separator ""
90
+ def run(argv, runopts = {})
150
91
 
151
- opts.on("-h", "--help",
152
- "Show this help message.") { puts opts; puts; exit }
92
+ # initialize options
93
+ @options = @initopts.merge(runopts)
153
94
 
154
- opts.parse!(ARGV)
155
- end
95
+ # backup current engine (if any)
96
+ cur_engine = Thread.current[:ridl_engine]
97
+ # store currently running engine for current thread
98
+ Thread.current[:ridl_engine] = self
156
99
 
157
- def IDL.push_input(idlfile, opts)
158
- @@idlstack << [idlfile, opts]
159
- end
100
+ begin
101
+ # parse arguments
102
+ begin
103
+ @optparser.parse!(argv)
104
+ rescue ArgumentError => ex
105
+ IDL.error(ex.inspect)
106
+ IDL.error(ex.backtrace.join("\n")) if IDL.verbose_level>0
107
+ return false
108
+ end
160
109
 
161
- def IDL.pop_input
162
- @@idlstack.shift
163
- end
110
+ if options[:preprocess]
164
111
 
165
- def IDL.peek_input
166
- @@idlstack.first
167
- end
112
+ ## PREPROCESSING
113
+ o = if options[:output].nil?
114
+ $stdout
115
+ else
116
+ File.open(options[:output], 'w+')
117
+ end
118
+ options[:output] = o
168
119
 
169
- def IDL.has_input?
170
- !@@idlstack.empty?
171
- end
120
+ input_base = File.basename(argv.first)
121
+ if (input_base != argv.first)
122
+ options[:xincludepaths] << File.dirname(argv.first)
123
+ end
172
124
 
173
- # main run method
174
- #
175
- def IDL.run
176
- # parse arguments
177
- begin
178
- parse_args
179
- rescue ArgumentError => ex
180
- IDL.error(ex.inspect)
181
- IDL.error(ex.backtrace.join("\n")) if $VERBOSE
182
- exit 1
183
- end
125
+ return !parse("#include \"#{input_base}\"", options).nil?
126
+ else
127
+ ## collect input files from commandline
128
+ collect_input(argv)
129
+
130
+ ## CODE GENERATION
131
+ while has_input?
132
+ # get input from stack
133
+ _idlfile, _opts = pop_input
134
+
135
+ _fio = if IO === _idlfile || StringIO === _idlfile
136
+ _idlfile
137
+ else
138
+ File.open(_idlfile, 'r')
139
+ end
140
+ raise RuntimeError, 'cannot read from STDOUT' if $stdout == _fio
141
+
142
+ # parse IDL source
143
+ IDL.log(1, "RIDL - parsing #{IO === _idlfile ? 'from STDIN': (StringIO === _idlfile ? 'from string' : _idlfile)}")
144
+
145
+ unless _parser = parse(_fio, _opts)
146
+ return false
147
+ end
184
148
 
185
- verbose_level = OPTIONS[:verbose]
149
+ # process parse result -> code generation
150
+ IDL.log(2, 'RIDL - starting code generation')
186
151
 
187
- if preprocessing?
188
- ## PREPROCESSING
189
- o = if OPTIONS[:output].nil?
190
- $stdout
191
- else
192
- File.open(OPTIONS[:output], "w+")
152
+ GenFile.transaction do
153
+ begin
154
+ backend.process_input(_parser, _opts)
155
+ rescue Backend::ProcessStop
156
+ IDL.log(2, "RIDL - processing #{IO === _idlfile ? 'from STDIN': (StringIO === _idlfile ? 'from string' : _idlfile)} stopped with \"#{$!.message}\"")
157
+ end
158
+ end
159
+ end
193
160
  end
194
- OPTIONS[:output] = o
161
+ ensure
162
+ # restore previous state
163
+ Thread.current[:ridl_engine] = cur_engine
164
+ end
165
+ true
166
+ end
195
167
 
196
- parser = ::IDL::Parser.new(OPTIONS)
197
- parser.yydebug = OPTIONS[:debug]
168
+ def parse(io, opts)
169
+ # parse IDL source
170
+ _parser = ::IDL::Parser.new(opts)
171
+ _parser.yydebug = opts[:debug]
198
172
 
199
173
  begin
200
- input_base = File.basename(ARGV.first)
201
- if (input_base != ARGV.first)
202
- OPTIONS[:includepaths] << File.dirname(ARGV.first)
203
- end
204
- parser.parse("#include \"#{input_base}\"")
174
+ _parser.parse(io)
205
175
  rescue => ex
206
176
  IDL.error(ex.inspect)
207
177
  IDL.error(ex.backtrace.join("\n")) unless ex.is_a? IDL::ParseError
178
+ return nil
208
179
  ensure
209
- o.close
180
+ io.close unless String === io || io == $stdin
210
181
  end
211
- else
182
+ _parser
183
+ end
184
+
185
+ private
186
+
187
+ def collect_input(argv)
212
188
  ## collect input files from commandline
213
- ARGV.each do |_arg|
214
- _opts = OPTIONS.dup
189
+ argv.each do |_arg|
190
+ _opts = options.dup
215
191
 
216
192
  _opts[:idlfile] = _arg
217
193
  if _opts[:search_incpath]
218
194
  _fname = _arg
219
195
  _fpath = if File.file?(_fname) && File.readable?(_fname)
220
- _fname
221
- else
222
- _fp = _opts[:includepaths].find do |_p|
223
- _f = _p + "/" + _fname
224
- File.file?(_f) && File.readable?(_f)
225
- end
226
- _opts[:outputdir] = _fp unless _fp.nil? || !_opts[:outputdir].nil?
227
- _fp += '/' + _fname unless _fp.nil?
228
- _fp
229
- end
196
+ _fname
197
+ else
198
+ _fp = _opts[:includepaths].find do |_p|
199
+ _f = _p + "/" + _fname
200
+ File.file?(_f) && File.readable?(_f)
201
+ end
202
+ _opts[:outputdir] = _fp unless _fp.nil? || !_opts[:outputdir].nil?
203
+ _fp += '/' + _fname unless _fp.nil?
204
+ _fp
205
+ end
230
206
  _arg = _fpath unless _fpath.nil?
231
207
  end
232
- _opts[:includepaths] << File.dirname(_arg)
208
+ _opts[:xincludepaths] << File.dirname(_arg)
233
209
 
234
210
  _opts[:outputdir] ||= '.'
235
211
 
@@ -238,59 +214,109 @@ module IDL
238
214
 
239
215
  ## if no IDL input file specified read from STDIN
240
216
  unless has_input?
241
- _opts = OPTIONS.dup
217
+ _opts = options.dup
242
218
  _opts[:outputdir] ||= '.'
243
219
  push_input($stdin, _opts)
244
220
  end
221
+ end
245
222
 
246
- ## CODE GENERATION
247
- while has_input?
248
- # get input from stack
249
- _idlfile, _opts = pop_input
250
-
251
- _fio = if IO === _idlfile || StringIO === _idlfile
252
- _idlfile
253
- else
254
- File.open(_idlfile, "r")
255
- end
256
- raise RuntimeError, 'cannot read from STDOUT' if $stdout == _fio
223
+ def init_optparser
224
+ script_name = File.basename($0, '.*')
225
+ if not script_name =~ /ridlc/
226
+ script_name = 'ruby '+$0
227
+ end
257
228
 
258
- # parse IDL source
259
- IDL.log(1, "RIDL - parsing #{IO === _idlfile ? 'from STDIN': _idlfile}")
229
+ # set up option parser with common options
230
+ opts = OptionParser.new
231
+ 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"+
234
+ " Active language mapping = :#{backend.name}"
235
+ opts.separator ""
236
+ opts.on("-I PATH", "--include=PATH", String,
237
+ "Adds include searchpath.",
238
+ "Default: nil") { |v| @options[:includepaths] << v }
239
+ opts.on('-Dmacro=[value]', String, 'defines preprocessor macro') { |v|
240
+ name, value = v.split('=')
241
+ @options[:macros][name] = (value ? value : true)
242
+ }
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'))
256
+ }
257
+ opts.on("--search-includepath",
258
+ "Use include paths to find main IDL source.",
259
+ "Default: off") { |v| @options[:search_incpath]=v }
260
+ 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 }
264
+ end
260
265
 
261
- _parser = ::IDL::Parser.new(_opts)
262
- _parser.yydebug = _opts[:debug]
266
+ # setup language mapping specific options
267
+ be_options = OptionList.new
268
+ @backend.setup_be(be_options, @initopts)
269
+ be_options.to_option_parser(opts, self)
270
+
271
+ opts.on('-V', '--version',
272
+ 'Show version information and exit.') {
273
+ puts "RIDL compiler #{@options[:macros][:__RIDL__]}"
274
+ puts RIDL_COPYRIGHT
275
+ puts '---'
276
+ @backend.print_version
277
+ exit
278
+ }
263
279
 
264
- begin
265
- _parser.parse(_fio)
266
- rescue => ex
267
- IDL.error(ex.inspect)
268
- IDL.error(ex.backtrace.join("\n")) unless ex.is_a? IDL::ParseError
269
- exit 1
270
- ensure
271
- _fio.close unless _fio == $stdin
272
- end
280
+ opts.separator ""
273
281
 
274
- # process parse result -> code generation
275
- IDL.log(2, 'RIDL - starting code generation')
282
+ opts.on('-h', '--help',
283
+ 'Show this help message.') { puts opts; puts; exit }
276
284
 
277
- GenFile.transaction do
278
- begin
279
- @@backend.process_input(_parser, _opts)
280
- rescue Backend::ProcessStop
281
- IDL.log(2, "RIDL - processing #{IO === _idlfile ? 'from STDIN': _idlfile} stopped from #{$!.message}")
282
- end
283
- end
284
- end
285
+ opts
285
286
  end
286
- end # IDL.run
287
+
288
+ end
289
+
290
+ def IDL.backend
291
+ Thread.current[:ridl_engine] ? Thread.current[:ridl_engine].backend : nil
292
+ end
293
+
294
+ def IDL.push_input(idlfile, opts)
295
+ Thread.current[:ridl_engine].push_input(idlfile, opts) if Thread.current[:ridl_engine]
296
+ end
297
+
298
+ def IDL.pop_input
299
+ Thread.current[:ridl_engine].pop_input if Thread.current[:ridl_engine]
300
+ end
301
+
302
+ def IDL.peek_input
303
+ Thread.current[:ridl_engine].peek_input if Thread.current[:ridl_engine]
304
+ end
305
+
306
+ def IDL.has_input?
307
+ Thread.current[:ridl_engine].has_input? if Thread.current[:ridl_engine]
308
+ end
287
309
 
288
310
  def IDL.verbose_level
289
- @@verbose_level
311
+ Thread.current[:ridl_engine] ? Thread.current[:ridl_engine].verbose_level : OPTIONS[:verbose]
290
312
  end
291
313
 
292
314
  def IDL.verbose_level=(l)
293
- @@verbose_level = l
315
+ if Thread.current[:ridl_engine]
316
+ Thread.current[:ridl_engine].verbose_level = l.to_i
317
+ else
318
+ OPTIONS[:verbose] = l.to_i
319
+ end
294
320
  end
295
321
 
296
322
  def IDL.log(level, message)
@@ -301,4 +327,41 @@ module IDL
301
327
  STDERR.puts(message)
302
328
  end
303
329
 
330
+ def IDL.init(argv = ARGV)
331
+ options = OPTIONS.dup
332
+
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
340
+
341
+ # add optional search paths for RIDL backends
342
+ $:.concat(ENV['RIDL_BE_PATH'].split(/:|;/)) if ENV['RIDL_BE_PATH']
343
+
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
352
+ end
353
+
354
+ # create RIDL engine
355
+ Thread.current[:ridl_engine] = Engine.new(@@be_name, options)
356
+ end
357
+
358
+ # main run method
359
+ #
360
+ def IDL.run(argv = ARGV)
361
+ # run default engine if available
362
+ if Thread.current[:ridl_engine]
363
+ exit(1) unless Thread.current[:ridl_engine].run(argv)
364
+ end
365
+ end # IDL.run
366
+
304
367
  end