Home | History | Annotate | Download | only in ruby
      1 #
      2 # This file is automatically generated. DO NOT MODIFY!
      3 #
      4 # install.rb
      5 #
      6 #   Copyright (c) 2000-2002 Minero Aoki <aamine (at] loveruby.net>
      7 #
      8 #   This program is free software.
      9 #   You can distribute/modify this program under the terms of
     10 #   the GNU Lesser General Public License version 2.
     11 #
     12 
     13 ### begin compat.rb
     14 
     15 unless Enumerable.instance_methods.include? 'inject' then
     16 module Enumerable
     17   def inject( result )
     18     each do |i|
     19       result = yield(result, i)
     20     end
     21     result
     22   end
     23 end
     24 end
     25 
     26 def File.read_all( fname )
     27   File.open(fname, 'rb') {|f| return f.read }
     28 end
     29 
     30 def File.write( fname, str )
     31   File.open(fname, 'wb') {|f| f.write str }
     32 end
     33 
     34 ### end compat.rb
     35 ### begin config.rb
     36 
     37 if i = ARGV.index(/\A--rbconfig=/) then
     38   file = $'
     39   ARGV.delete_at(i)
     40   require file
     41 else
     42   require 'rbconfig'
     43 end
     44 
     45 
     46 class ConfigTable
     47 
     48   c = ::Config::CONFIG
     49 
     50   rubypath = c['bindir'] + '/' + c['ruby_install_name']
     51 
     52   major = c['MAJOR'].to_i
     53   minor = c['MINOR'].to_i
     54   teeny = c['TEENY'].to_i
     55   version = "#{major}.#{minor}"
     56 
     57   # ruby ver. >= 1.4.4?
     58   newpath_p = ((major >= 2) or
     59                ((major == 1) and
     60                 ((minor >= 5) or
     61                  ((minor == 4) and (teeny >= 4)))))
     62   
     63   re = Regexp.new('\A' + Regexp.quote(c['prefix']))
     64   subprefix = lambda {|path|
     65       re === path and path.sub(re, '$prefix')
     66   }
     67 
     68   if c['rubylibdir'] then
     69     # 1.6.3 < V
     70     stdruby    = subprefix.call(c['rubylibdir'])
     71     siteruby   = subprefix.call(c['sitedir'])
     72     versite    = subprefix.call(c['sitelibdir'])
     73     sodir      = subprefix.call(c['sitearchdir'])
     74   elsif newpath_p then
     75     # 1.4.4 <= V <= 1.6.3
     76     stdruby    = "$prefix/lib/ruby/#{version}"
     77     siteruby   = subprefix.call(c['sitedir'])
     78     versite    = siteruby + '/' + version
     79     sodir      = "$site-ruby/#{c['arch']}"
     80   else
     81     # V < 1.4.4
     82     stdruby    = "$prefix/lib/ruby/#{version}"
     83     siteruby   = "$prefix/lib/ruby/#{version}/site_ruby"
     84     versite    = siteruby
     85     sodir      = "$site-ruby/#{c['arch']}"
     86   end
     87 
     88   DESCRIPTER = [
     89     [ 'prefix',    [ c['prefix'],
     90                      'path',
     91                      'path prefix of target environment' ] ],
     92     [ 'std-ruby',  [ stdruby,
     93                      'path',
     94                      'the directory for standard ruby libraries' ] ],
     95     [ 'site-ruby-common', [ siteruby,
     96                      'path',
     97                      'the directory for version-independent non-standard ruby libraries' ] ],
     98     [ 'site-ruby', [ versite,
     99                      'path',
    100                      'the directory for non-standard ruby libraries' ] ],
    101     [ 'bin-dir',   [ '$prefix/bin',
    102                      'path',
    103                      'the directory for commands' ] ],
    104     [ 'rb-dir',    [ '$site-ruby',
    105                      'path',
    106                      'the directory for ruby scripts' ] ],
    107     [ 'so-dir',    [ sodir,
    108                      'path',
    109                      'the directory for ruby extentions' ] ],
    110     [ 'data-dir',  [ '$prefix/share',
    111                      'path',
    112                      'the directory for shared data' ] ],
    113     [ 'ruby-path', [ rubypath,
    114                      'path',
    115                      'path to set to #! line' ] ],
    116     [ 'ruby-prog', [ rubypath,
    117                      'name',
    118                      'the ruby program using for installation' ] ],
    119     [ 'make-prog', [ 'make',
    120                      'name',
    121                      'the make program to compile ruby extentions' ] ],
    122     [ 'without-ext', [ 'no',
    123                        'yes/no',
    124                        'does not compile/install ruby extentions' ] ]
    125   ]
    126 
    127   SAVE_FILE = 'config.save'
    128 
    129   def ConfigTable.each_name( &block )
    130     keys().each( &block )
    131   end
    132 
    133   def ConfigTable.keys
    134     DESCRIPTER.collect {|k,*dummy| k }
    135   end
    136 
    137   def ConfigTable.each_definition( &block )
    138     DESCRIPTER.each( &block )
    139   end
    140 
    141   def ConfigTable.get_entry( name )
    142     name, ent = DESCRIPTER.assoc(name)
    143     ent
    144   end
    145 
    146   def ConfigTable.get_entry!( name )
    147     get_entry(name) or raise ArgumentError, "no such config: #{name}"
    148   end
    149 
    150   def ConfigTable.add_entry( name, vals )
    151     ConfigTable::DESCRIPTER.push [name,vals]
    152   end
    153 
    154   def ConfigTable.remove_entry( name )
    155     get_entry name or raise ArgumentError, "no such config: #{name}"
    156     DESCRIPTER.delete_if {|n,arr| n == name }
    157   end
    158 
    159   def ConfigTable.config_key?( name )
    160     get_entry(name) ? true : false
    161   end
    162 
    163   def ConfigTable.bool_config?( name )
    164     ent = get_entry(name) or return false
    165     ent[1] == 'yes/no'
    166   end
    167 
    168   def ConfigTable.value_config?( name )
    169     ent = get_entry(name) or return false
    170     ent[1] != 'yes/no'
    171   end
    172 
    173   def ConfigTable.path_config?( name )
    174     ent = get_entry(name) or return false
    175     ent[1] == 'path'
    176   end
    177 
    178 
    179   class << self
    180 
    181     alias newobj new
    182 
    183     def new
    184       c = newobj()
    185       c.__send__ :init
    186       c
    187     end
    188 
    189     def load
    190       c = newobj()
    191       File.file? SAVE_FILE or
    192               raise InstallError, "#{File.basename $0} config first"
    193       File.foreach( SAVE_FILE ) do |line|
    194         k, v = line.split( '=', 2 )
    195         c.instance_eval {
    196             @table[k] = v.strip
    197         }
    198       end
    199       c
    200     end
    201   
    202   end
    203 
    204   def initialize
    205     @table = {}
    206   end
    207 
    208   def init
    209     DESCRIPTER.each do |k, (default, vname, desc, default2)|
    210       @table[k] = default
    211     end
    212   end
    213   private :init
    214 
    215   def save
    216     File.open( SAVE_FILE, 'w' ) {|f|
    217         @table.each do |k, v|
    218           f.printf "%s=%s\n", k, v if v
    219         end
    220     }
    221   end
    222 
    223   def []=( k, v )
    224     ConfigTable.config_key? k or raise InstallError, "unknown config option #{k}"
    225     if ConfigTable.path_config? k then
    226       @table[k] = (v[0,1] != '$') ? File.expand_path(v) : v
    227     else
    228       @table[k] = v
    229     end
    230   end
    231     
    232   def []( key )
    233     @table[key] or return nil
    234     @table[key].gsub( %r<\$([^/]+)> ) { self[$1] }
    235   end
    236 
    237   def set_raw( key, val )
    238     @table[key] = val
    239   end
    240 
    241   def get_raw( key )
    242     @table[key]
    243   end
    244 
    245 end
    246 
    247 
    248 class MetaConfigEnvironment
    249 
    250   def self.eval_file( file )
    251     return unless File.file? file
    252     new.instance_eval File.read_all(file), file, 1
    253   end
    254 
    255   private
    256 
    257   def config_names
    258     ConfigTable.keys
    259   end
    260 
    261   def config?( name )
    262     ConfigTable.config_key? name
    263   end
    264 
    265   def bool_config?( name )
    266     ConfigTable.bool_config? name
    267   end
    268 
    269   def value_config?( name )
    270     ConfigTable.value_config? name
    271   end
    272 
    273   def path_config?( name )
    274     ConfigTable.path_config? name
    275   end
    276 
    277   def add_config( name, argname, default, desc )
    278     ConfigTable.add_entry name,[default,argname,desc]
    279   end
    280 
    281   def add_path_config( name, default, desc )
    282     add_config name, 'path', default, desc
    283   end
    284 
    285   def add_bool_config( name, default, desc )
    286     add_config name, 'yes/no', default ? 'yes' : 'no', desc
    287   end
    288 
    289   def set_config_default( name, default )
    290     if bool_config? name then
    291       ConfigTable.get_entry!(name)[0] = default ? 'yes' : 'no'
    292     else
    293       ConfigTable.get_entry!(name)[0] = default
    294     end
    295   end
    296 
    297   def remove_config( name )
    298     ent = ConfigTable.get_entry(name)
    299     ConfigTable.remove_entry name
    300     ent
    301   end
    302 
    303 end
    304 
    305 ### end config.rb
    306 ### begin fileop.rb
    307 
    308 module FileOperations
    309 
    310   def mkdir_p( dname, prefix = nil )
    311     dname = prefix + dname if prefix
    312     $stderr.puts "mkdir -p #{dname}" if verbose?
    313     return if no_harm?
    314 
    315     # does not check '/'... it's too abnormal case
    316     dirs = dname.split(%r_(?=/)_)
    317     if /\A[a-z]:\z/i === dirs[0] then
    318       disk = dirs.shift
    319       dirs[0] = disk + dirs[0]
    320     end
    321     dirs.each_index do |idx|
    322       path = dirs[0..idx].join('')
    323       Dir.mkdir path unless dir? path
    324     end
    325   end
    326 
    327   def rm_f( fname )
    328     $stderr.puts "rm -f #{fname}" if verbose?
    329     return if no_harm?
    330 
    331     if File.exist? fname or File.symlink? fname then
    332       File.chmod 0777, fname
    333       File.unlink fname
    334     end
    335   end
    336 
    337   def rm_rf( dn )
    338     $stderr.puts "rm -rf #{dn}" if verbose?
    339     return if no_harm?
    340 
    341     Dir.chdir dn
    342     Dir.foreach('.') do |fn|
    343       next if fn == '.'
    344       next if fn == '..'
    345       if dir? fn then
    346         verbose_off {
    347             rm_rf fn
    348         }
    349       else
    350         verbose_off {
    351             rm_f fn
    352         }
    353       end
    354     end
    355     Dir.chdir '..'
    356     Dir.rmdir dn
    357   end
    358 
    359   def mv( src, dest )
    360     rm_f dest
    361     begin
    362       File.link src, dest
    363     rescue
    364       File.write dest, File.read_all(src)
    365       File.chmod File.stat(src).mode, dest
    366     end
    367     rm_f src
    368   end
    369 
    370   def install( from, dest, mode, prefix = nil )
    371     $stderr.puts "install #{from} #{dest}" if verbose?
    372     return if no_harm?
    373 
    374     realdest = prefix + dest if prefix
    375     if dir? realdest then
    376       realdest += '/' + File.basename(from)
    377     end
    378     str = File.read_all(from)
    379     if diff? str, realdest then
    380       verbose_off {
    381           rm_f realdest if File.exist? realdest
    382       }
    383       File.write realdest, str
    384       File.chmod mode, realdest
    385 
    386       File.open( objdir + '/InstalledFiles', 'a' ) {|f| f.puts realdest }
    387     end
    388   end
    389 
    390   def diff?( orig, targ )
    391     return true unless File.exist? targ
    392     orig != File.read_all(targ)
    393   end
    394 
    395   def command( str )
    396     $stderr.puts str if verbose?
    397     system str or raise RuntimeError, "'system #{str}' failed"
    398   end
    399 
    400   def ruby( str )
    401     command config('ruby-prog') + ' ' + str
    402   end
    403 
    404   def dir?( dname )
    405     # for corrupted windows stat()
    406     File.directory?( (dname[-1,1] == '/') ? dname : dname + '/' )
    407   end
    408 
    409   def all_files( dname )
    410     Dir.open( dname ) {|d|
    411         return d.find_all {|n| File.file? "#{dname}/#{n}" }
    412     }
    413   end
    414 
    415   def all_dirs( dname )
    416     Dir.open( dname ) {|d|
    417         return d.find_all {|n| dir? "#{dname}/#{n}" } - %w(. ..)
    418     }
    419   end
    420 
    421 end
    422 
    423 ### end fileop.rb
    424 ### begin base.rb
    425 
    426 class InstallError < StandardError; end
    427 
    428 
    429 class Installer
    430 
    431   Version   = '3.1.2'
    432   Copyright = 'Copyright (c) 2000-2002 Minero Aoki'
    433 
    434 
    435   @toplevel = nil
    436 
    437   def self.declear_toplevel_installer( inst )
    438     @toplevel and
    439         raise ArgumentError, 'more than one toplevel installer decleared'
    440     @toplevel = inst
    441   end
    442 
    443   def self.toplevel_installer
    444     @toplevel
    445   end
    446 
    447 
    448   FILETYPES = %w( bin lib ext data )
    449 
    450   include FileOperations
    451 
    452   def initialize( config, opt, srcroot, objroot )
    453     @config = config
    454     @options = opt
    455     @srcdir = File.expand_path(srcroot)
    456     @objdir = File.expand_path(objroot)
    457     @currdir = '.'
    458   end
    459 
    460   def inspect
    461     "#<#{type} #{__id__}>"
    462   end
    463 
    464   #
    465   # configs/options
    466   #
    467 
    468   def get_config( key )
    469     @config[key]
    470   end
    471 
    472   alias config get_config
    473 
    474   def set_config( key, val )
    475     @config[key] = val
    476   end
    477 
    478   def no_harm?
    479     @options['no-harm']
    480   end
    481 
    482   def verbose?
    483     @options['verbose']
    484   end
    485 
    486   def verbose_off
    487     save, @options['verbose'] = @options['verbose'], false
    488     yield
    489     @options['verbose'] = save
    490   end
    491 
    492   #
    493   # srcdir/objdir
    494   #
    495 
    496   attr_reader :srcdir
    497   alias srcdir_root srcdir
    498   alias package_root srcdir
    499 
    500   def curr_srcdir
    501     "#{@srcdir}/#{@currdir}"
    502   end
    503 
    504   attr_reader :objdir
    505   alias objdir_root objdir
    506 
    507   def curr_objdir
    508     "#{@objdir}/#{@currdir}"
    509   end
    510 
    511   def srcfile( path )
    512     curr_srcdir + '/' + path
    513   end
    514 
    515   def srcexist?( path )
    516     File.exist? srcfile(path)
    517   end
    518 
    519   def srcdirectory?( path )
    520     dir? srcfile(path)
    521   end
    522   
    523   def srcfile?( path )
    524     File.file? srcfile(path)
    525   end
    526 
    527   def srcentries( path = '.' )
    528     Dir.open( curr_srcdir + '/' + path ) {|d|
    529         return d.to_a - %w(. ..) - hookfilenames
    530     }
    531   end
    532 
    533   def srcfiles( path = '.' )
    534     srcentries(path).find_all {|fname|
    535         File.file? File.join(curr_srcdir, path, fname)
    536     }
    537   end
    538 
    539   def srcdirectories( path = '.' )
    540     srcentries(path).find_all {|fname|
    541         dir? File.join(curr_srcdir, path, fname)
    542     }
    543   end
    544 
    545   def dive_into( rel )
    546     return unless dir? "#{@srcdir}/#{rel}"
    547 
    548     dir = File.basename(rel)
    549     Dir.mkdir dir unless dir? dir
    550     save = Dir.pwd
    551     Dir.chdir dir
    552     $stderr.puts '---> ' + rel if verbose?
    553     @currdir = rel
    554     yield
    555     Dir.chdir save
    556     $stderr.puts '<--- ' + rel if verbose?
    557     @currdir = File.dirname(rel)
    558   end
    559 
    560   #
    561   # config
    562   #
    563 
    564   def exec_config
    565     exec_task_traverse 'config'
    566   end
    567 
    568   def config_dir_bin( rel )
    569   end
    570 
    571   def config_dir_lib( rel )
    572   end
    573 
    574   def config_dir_ext( rel )
    575     extconf if extdir? curr_srcdir
    576   end
    577 
    578   def extconf
    579     opt = @options['config-opt'].join(' ')
    580     command "#{config('ruby-prog')} #{curr_srcdir}/extconf.rb #{opt}"
    581   end
    582 
    583   def config_dir_data( rel )
    584   end
    585 
    586   #
    587   # setup
    588   #
    589 
    590   def exec_setup
    591     exec_task_traverse 'setup'
    592   end
    593 
    594   def setup_dir_bin( relpath )
    595     all_files( curr_srcdir ).each do |fname|
    596       add_rubypath "#{curr_srcdir}/#{fname}"
    597     end
    598   end
    599 
    600   SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
    601 
    602   def add_rubypath( path )
    603     $stderr.puts %Q<set #! line to "\#!#{config('ruby-path')}" for #{path} ...> if verbose?
    604     return if no_harm?
    605 
    606     tmpfile = File.basename(path) + '.tmp'
    607     begin
    608       File.open( path ) {|r|
    609       File.open( tmpfile, 'w' ) {|w|
    610           first = r.gets
    611           return unless SHEBANG_RE === first   # reject '/usr/bin/env ruby'
    612 
    613           w.print first.sub( SHEBANG_RE, '#!' + config('ruby-path') )
    614           w.write r.read
    615       } }
    616       mv tmpfile, File.basename(path)
    617     ensure
    618       rm_f tmpfile if File.exist? tmpfile
    619     end
    620   end
    621 
    622   def setup_dir_lib( relpath )
    623   end
    624 
    625   def setup_dir_ext( relpath )
    626     if extdir? curr_srcdir then
    627       make
    628     end
    629   end
    630 
    631   def make
    632     command config('make-prog')
    633   end
    634 
    635   def setup_dir_data( relpath )
    636   end
    637 
    638   #
    639   # install
    640   #
    641 
    642   def exec_install
    643     exec_task_traverse 'install'
    644   end
    645 
    646   def install_dir_bin( rel )
    647     install_files targfiles, config('bin-dir') + '/' + rel, 0755
    648   end
    649 
    650   def install_dir_lib( rel )
    651     install_files targfiles, config('rb-dir') + '/' + rel, 0644
    652   end
    653 
    654   def install_dir_ext( rel )
    655     if extdir? curr_srcdir then
    656       install_dir_ext_main File.dirname(rel)
    657     end
    658   end
    659 
    660   def install_dir_ext_main( rel )
    661     install_files allext('.'), config('so-dir') + '/' + rel, 0555
    662   end
    663 
    664   def install_dir_data( rel )
    665     install_files targfiles, config('data-dir') + '/' + rel, 0644
    666   end
    667 
    668   def install_files( list, dest, mode )
    669     mkdir_p dest, @options['install-prefix']
    670     list.each do |fname|
    671       install fname, dest, mode, @options['install-prefix']
    672     end
    673   end
    674   
    675   def targfiles
    676     (targfilenames() - hookfilenames()).collect {|fname|
    677         File.exist?(fname) ? fname : File.join(curr_srcdir(), fname)
    678     }
    679   end
    680 
    681   def targfilenames
    682     [ curr_srcdir(), '.' ].inject([]) {|ret, dir|
    683         ret | all_files(dir)
    684     }
    685   end
    686 
    687   def hookfilenames
    688     %w( pre-%s post-%s pre-%s.rb post-%s.rb ).collect {|fmt|
    689         %w( config setup install clean ).collect {|t| sprintf fmt, t }
    690     }.flatten
    691   end
    692 
    693   def allext( dir )
    694     _allext(dir) or raise InstallError,
    695         "no extention exists: Have you done 'ruby #{$0} setup' ?"
    696   end
    697 
    698   DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/
    699 
    700   def _allext( dir )
    701     Dir.open( dir ) {|d|
    702         return d.find_all {|fname| DLEXT === fname }
    703     }
    704   end
    705 
    706   #
    707   # clean
    708   #
    709 
    710   def exec_clean
    711     exec_task_traverse 'clean'
    712     rm_f 'config.save'
    713     rm_f 'InstalledFiles'
    714   end
    715 
    716   def clean_dir_bin( rel )
    717   end
    718 
    719   def clean_dir_lib( rel )
    720   end
    721 
    722   def clean_dir_ext( rel )
    723     clean
    724   end
    725   
    726   def clean
    727     command config('make-prog') + ' clean' if File.file? 'Makefile'
    728   end
    729 
    730   def clean_dir_data( rel )
    731   end
    732 
    733   #
    734   # lib
    735   #
    736 
    737   def exec_task_traverse( task )
    738     run_hook 'pre-' + task
    739     FILETYPES.each do |type|
    740       if config('without-ext') == 'yes' and type == 'ext' then
    741         $stderr.puts 'skipping ext/* by user option' if verbose?
    742         next
    743       end
    744       traverse task, type, task + '_dir_' + type
    745     end
    746     run_hook 'post-' + task
    747   end
    748 
    749   def traverse( task, rel, mid )
    750     dive_into( rel ) {
    751         run_hook 'pre-' + task
    752         __send__ mid, rel.sub( %r_\A.*?(?:/|\z)_, '' )
    753         all_dirs( curr_srcdir ).each do |d|
    754           traverse task, rel + '/' + d, mid
    755         end
    756         run_hook 'post-' + task
    757     }
    758   end
    759 
    760   def run_hook( name )
    761     try_run_hook curr_srcdir + '/' + name           or
    762     try_run_hook curr_srcdir + '/' + name + '.rb'
    763   end
    764 
    765   def try_run_hook( fname )
    766     return false unless File.file? fname
    767 
    768     env = self.dup
    769     begin
    770       env.instance_eval File.read_all(fname), fname, 1
    771     rescue
    772       raise InstallError, "hook #{fname} failed:\n" + $!.message
    773     end
    774     true
    775   end
    776 
    777   def extdir?( dir )
    778     File.exist? dir + '/MANIFEST'
    779   end
    780 
    781 end
    782 
    783 ### end base.rb
    784 ### begin toplevel.rb
    785 
    786 class ToplevelInstaller < Installer
    787 
    788   TASKS = [
    789     [ 'config',   'saves your configurations' ],
    790     [ 'show',     'shows current configuration' ],
    791     [ 'setup',    'compiles extention or else' ],
    792     [ 'install',  'installs files' ],
    793     [ 'clean',    "does `make clean' for each extention" ]
    794   ]
    795 
    796 
    797   def initialize( root )
    798     super nil, {'verbose' => true}, root, '.'
    799     Installer.declear_toplevel_installer self
    800   end
    801 
    802 
    803   def execute
    804     run_metaconfigs
    805 
    806     case task = parsearg_global()
    807     when 'config'
    808       @config = ConfigTable.new
    809     else
    810       @config = ConfigTable.load
    811     end
    812     parsearg_TASK task
    813 
    814     exectask task
    815   end
    816 
    817 
    818   def run_metaconfigs
    819     MetaConfigEnvironment.eval_file "#{srcdir_root}/#{metaconfig}"
    820   end
    821 
    822   def metaconfig
    823     'metaconfig'
    824   end
    825 
    826 
    827   def exectask( task )
    828     if task == 'show' then
    829       exec_show
    830     else
    831       try task
    832     end
    833   end
    834 
    835   def try( task )
    836     $stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose?
    837     begin
    838       __send__ 'exec_' + task
    839     rescue
    840       $stderr.printf "%s failed\n", task
    841       raise
    842     end
    843     $stderr.printf "#{File.basename $0}: %s done.\n", task if verbose?
    844   end
    845 
    846   #
    847   # processing arguments
    848   #
    849 
    850   def parsearg_global
    851     task_re = /\A(?:#{TASKS.collect {|i| i[0] }.join '|'})\z/
    852 
    853     while arg = ARGV.shift do
    854       case arg
    855       when /\A\w+\z/
    856         task_re === arg or raise InstallError, "wrong task: #{arg}"
    857         return arg
    858 
    859       when '-q', '--quiet'
    860         @options['verbose'] = false
    861 
    862       when       '--verbose'
    863         @options['verbose'] = true
    864 
    865       when '-h', '--help'
    866         print_usage $stdout
    867         exit 0
    868 
    869       when '-v', '--version'
    870         puts "#{File.basename $0} version #{Version}"
    871         exit 0
    872       
    873       when '--copyright'
    874         puts Copyright
    875         exit 0
    876 
    877       else
    878         raise InstallError, "unknown global option '#{arg}'"
    879       end
    880     end
    881 
    882     raise InstallError, 'no task or global option given'
    883   end
    884 
    885 
    886   def parsearg_TASK( task )
    887     mid = "parsearg_#{task}"
    888     if respond_to? mid, true then
    889       __send__ mid
    890     else
    891       ARGV.empty? or
    892           raise InstallError, "#{task}:  unknown options: #{ARGV.join ' '}"
    893     end
    894   end
    895 
    896   def parsearg_config
    897     re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
    898     @options['config-opt'] = []
    899 
    900     while i = ARGV.shift do
    901       if /\A--?\z/ === i then
    902         @options['config-opt'] = ARGV.dup
    903         break
    904       end
    905       m = re.match(i) or raise InstallError, "config: unknown option #{i}"
    906       name, value = m.to_a[1,2]
    907       if value then
    908         if ConfigTable.bool_config?(name) then
    909           /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i === value or raise InstallError, "config: --#{name} allows only yes/no for argument"
    910           value = (/\Ay(es)?|\At(rue)/i === value) ? 'yes' : 'no'
    911         end
    912       else
    913         ConfigTable.bool_config?(name) or raise InstallError, "config: --#{name} requires argument"
    914         value = 'yes'
    915       end
    916       @config[name] = value
    917     end
    918   end
    919 
    920   def parsearg_install
    921     @options['no-harm'] = false
    922     @options['install-prefix'] = ''
    923     while a = ARGV.shift do
    924       case a
    925       when /\A--no-harm\z/
    926         @options['no-harm'] = true
    927       when /\A--prefix=(.*)\z/
    928         path = $1
    929         path = File.expand_path(path) unless path[0,1] == '/'
    930         @options['install-prefix'] = path
    931       else
    932         raise InstallError, "install: unknown option #{a}"
    933       end
    934     end
    935   end
    936 
    937 
    938   def print_usage( out )
    939     out.puts
    940     out.puts 'Usage:'
    941     out.puts "  ruby #{File.basename $0} <global option>"
    942     out.puts "  ruby #{File.basename $0} [<global options>] <task> [<task options>]"
    943 
    944     fmt = "  %-20s %s\n"
    945     out.puts
    946     out.puts 'Global options:'
    947     out.printf fmt, '-q,--quiet',   'suppress message outputs'
    948     out.printf fmt, '   --verbose', 'output messages verbosely'
    949     out.printf fmt, '-h,--help',    'print this message'
    950     out.printf fmt, '-v,--version', 'print version and quit'
    951     out.printf fmt, '--copyright',  'print copyright and quit'
    952 
    953     out.puts
    954     out.puts 'Tasks:'
    955     TASKS.each do |name, desc|
    956       out.printf "  %-10s  %s\n", name, desc
    957     end
    958 
    959     out.puts
    960     out.puts 'Options for config:'
    961     ConfigTable.each_definition do |name, (default, arg, desc, default2)|
    962       out.printf "  %-20s %s [%s]\n",
    963                  '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
    964                  desc,
    965                  default2 || default
    966     end
    967     out.printf "  %-20s %s [%s]\n",
    968         '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
    969 
    970     out.puts
    971     out.puts 'Options for install:'
    972     out.printf "  %-20s %s [%s]\n",
    973         '--no-harm', 'only display what to do if given', 'off'
    974 
    975     out.puts
    976   end
    977 
    978   #
    979   # config
    980   #
    981 
    982   def exec_config
    983     super
    984     @config.save
    985   end
    986 
    987   #
    988   # show
    989   #
    990 
    991   def exec_show
    992     ConfigTable.each_name do |k|
    993       v = @config.get_raw(k)
    994       if not v or v.empty? then
    995         v = '(not specified)'
    996       end
    997       printf "%-10s %s\n", k, v
    998     end
    999   end
   1000 
   1001 end
   1002 
   1003 ### end toplevel.rb
   1004 
   1005 if $0 == __FILE__ then
   1006   begin
   1007     installer = ToplevelInstaller.new( File.dirname($0) )
   1008     installer.execute
   1009   rescue
   1010     raise if $DEBUG
   1011     $stderr.puts $!.message
   1012     $stderr.puts "try 'ruby #{$0} --help' for usage"
   1013     exit 1
   1014   end
   1015 end
   1016