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