class IDL::Engine
def backend
def backend @backend end
def collect_input(argv)
def collect_input(argv) ## collect input files from commandline argv.each do |_arg| _opts = options.dup _opts[:idlfile] = _arg if _opts[:search_incpath] _fname = _arg _fpath = if File.file?(_fname) && File.readable?(_fname) _fname else _fp = _opts[:includepaths].find do |_p| _f = _p + "/" + _fname File.file?(_f) && File.readable?(_f) end _opts[:outputdir] = _fp unless _fp.nil? || !_opts[:outputdir].nil? _fp += '/' + _fname unless _fp.nil? _fp end _arg = _fpath unless _fpath.nil? end _opts[:xincludepaths] << File.dirname(_arg) _opts[:outputdir] ||= '.' push_input(_arg, _opts) end ## if no IDL input file specified read from STDIN unless has_input? _opts = options.dup _opts[:outputdir] ||= '.' push_input($stdin, _opts) end end
def has_input?
def has_input? !@inputstack.empty? end
def init_optparser
def init_optparser script_name = File.basename($0, '.*') if not script_name =~ /ridlc/ script_name = 'ruby '+$0 end # set up option parser with common options opts = OptionParser.new opts.banner = "Usage: #{script_name} [:backend] [options] [<idlfile> [<idlfile> ...]]\n\n" + " backend\t\tSpecifies the IDL language mapping backend to use.\n"+ " \t\tDefault = :null\n\n"+ " Active language mapping = :#{backend.name}" opts.separator "" opts.on("-I PATH", "--include=PATH", String, "Adds include searchpath.", "Default: nil") { |v| @options[:includepaths] << v } opts.on('-Dmacro=[value]', String, 'defines preprocessor macro') { |v| name, value = v.split('=') @options[:macros][name] = (value ? value : true) } opts.on("-n NAMESPACE", "--namespace=NAMESPACE", String, "Defines rootlevel enclosing namespace.", "Default: nil") { |v| @options[:namespace]=v } opts.on("-v", "--verbose", "Set verbosity level. Repeat to increment.", "Default: 0") { |v| @options[:verbose] += 1 } opts.on("--debug", "Set parser debug mode. Don't do this at home!", "Default: off") { |v| @options[:debug] = true } opts.on('--stdidl', 'Adds include path to standard IDL files provided with RIDL.', 'Default: not set') { |v| @options[:includepaths] << File.expand_path(File.join(File.dirname(__FILE__), '..', 'idl')) } opts.on("--search-includepath", "Use include paths to find main IDL source.", "Default: off") { |v| @options[:search_incpath]=v } if @initopts[:preprocess] opts.on("--output=FILE", String, "Specifies filename to generate output in.", "Default: basename(idlfile)-'.idl'+<postfix>+<ext>") { |v| @options[:output]=v } end # setup language mapping specific options be_options = OptionList.new @backend.setup_be(be_options, @initopts) be_options.to_option_parser(opts, self) opts.on('-V', '--version', 'Show version information and exit.') { puts "RIDL compiler #{@options[:macros][:__RIDL__]}" puts RIDL_COPYRIGHT puts '---' @backend.print_version exit } opts.separator "" opts.on('-h', '--help', 'Show this help message.') { puts opts; puts; exit } opts end
def initialize(backend, options)
def initialize(backend, options) @backend = backend ? Backend.load(backend) : Backend.null_be @initopts = options.merge({ backend: @backend.name, macros: options[:macros].merge({ __RIDLBE__: @backend.name.to_s, __RIDLBE_VER__: @backend.version }) }) @optparser = init_optparser @inputstack = [] @options = nil end
def options
def options @options || @initopts end
def parse(io, opts)
def parse(io, opts) # parse IDL source _parser = ::IDL::Parser.new(opts) _parser.yydebug = opts[:debug] begin _parser.parse(io) rescue => ex IDL.error(ex.inspect) IDL.error(ex.backtrace.join("\n")) unless ex.is_a? IDL::ParseError return nil ensure io.close unless String === io || io == $stdin end _parser end
def peek_input
def peek_input @inputstack.first end
def pop_input
def pop_input @inputstack.shift end
def push_input(idlfile, opts)
def push_input(idlfile, opts) @inputstack << [idlfile, opts] end
def run(argv, runopts = {})
def run(argv, runopts = {}) # initialize options @options = @initopts.merge(runopts) # backup current engine (if any) cur_engine = Thread.current[:ridl_engine] # store currently running engine for current thread Thread.current[:ridl_engine] = self begin # parse arguments begin @optparser.parse!(argv) rescue ArgumentError => ex IDL.error(ex.inspect) IDL.error(ex.backtrace.join("\n")) if IDL.verbose_level>0 return false end if options[:preprocess] ## PREPROCESSING o = if options[:output].nil? $stdout else File.open(options[:output], 'w+') end options[:output] = o input_base = File.basename(argv.first) if (input_base != argv.first) options[:xincludepaths] << File.dirname(argv.first) end return !parse("#include \"#{input_base}\"", options).nil? else ## collect input files from commandline collect_input(argv) ## CODE GENERATION while has_input? # get input from stack _idlfile, _opts = pop_input _fio = if IO === _idlfile || StringIO === _idlfile _idlfile else File.open(_idlfile, 'r') end raise RuntimeError, 'cannot read from STDOUT' if $stdout == _fio # parse IDL source IDL.log(1, "RIDL - parsing #{IO === _idlfile ? 'from STDIN': (StringIO === _idlfile ? 'from string' : _idlfile)}") unless _parser = parse(_fio, _opts) return false end # process parse result -> code generation IDL.log(2, 'RIDL - starting code generation') GenFile.transaction do begin backend.process_input(_parser, _opts) rescue Backend::ProcessStop IDL.log(2, "RIDL - processing #{IO === _idlfile ? 'from STDIN': (StringIO === _idlfile ? 'from string' : _idlfile)} stopped with \"#{$!.message}\"") end end end end ensure # restore previous state Thread.current[:ridl_engine] = cur_engine end true end
def verbose_level
def verbose_level options[:verbose] end
def verbose_level=(l)
def verbose_level=(l) options[:verbose] = l end