Change soft-fail to use the config, rather than env
[rbx.git] / kernel / loader.rb
blob3ac040d0144fc8ccfe29feb79082e06f2da5c25e
1 # Contained first is the system startup code.
3 # Re-setup all the stdio channels, to pull in new ivars
5 STDOUT.setup
6 STDIN.setup
7 STDERR.setup
9 begin
10   Array.after_loaded
11   Module.after_loaded
13   Class.after_loaded
14   Hash.after_loaded
15   Kernel.after_loaded
16   Math.after_loaded
17   FileTest.after_loaded
18   Thread.after_loaded
19   Struct.after_loaded
20   Signal.after_loaded
21   ObjectSpace.after_loaded
22   IO.after_loaded
23   IO::BidirectionalPipe.after_loaded
24   Object.after_loaded
25   File.after_loaded
26   String.after_loaded
28   Ar.after_loaded
30   ENV = EnvironmentVariables.new
32   # define a global "start time" to use for process calculation
33   $STARTUP_TIME = Time.now
34 rescue Object => e
35   STDOUT << "Error detected running loader startup stage:\n"
36   STDOUT << "  #{e.message} (#{e.class})\n"
37   STDOUT << e.backtrace
38   exit 2
39 end
41 # Set up a handler for SIGINT that raises Interrupt on the main thread
42 Signal.action("INT") do |_|
43   thread = Thread.main
45   if thread.alive?
46     thread.raise Interrupt, "Thread has been interrupted"
47   else # somehow..?
48     puts "Signal received, but the main thread is dead."
49     puts "Unable to continue."
50     exit! 1
51   end
52 end
54 # This is the end of the kernel and the beginning of specified
55 # code. We read out of ARGV to figure out what the user is
56 # trying to do.
58 # Setup $LOAD_PATH.
60 additions = []
62 # The main stdlib location
63 additions << Rubinius::CODE_PATH
65 $LOAD_PATH.insert($LOAD_PATH.index('.'), *additions)
67 if ENV['RUBYLIB'] and not ENV['RUBYLIB'].empty? then
68   $LOAD_PATH.unshift(*ENV['RUBYLIB'].split(':'))
69 end
71 # Pull it out now so that later unshifts don't obsure it.
72 main_lib = $LOAD_PATH.first
74 # Allow system wide code preloading
76 ['/etc/rbxrc',"#{ENV['HOME']}/.rbxrc",ENV['RBX_PRELOAD']].each do |file|
77   begin
78     load file if file and File.exist?(file)
79   rescue LoadError
80     nil
81   end
82 end
84 # Parse options here!
85 RBS_USAGE = <<END
86 Usage: rubinius [options] [file]
87   File may be any valid Ruby source file (.rb) or a compiled Ruby file (.rbc).
89 Options:
90   -d             Enable debugging output and set $DEBUG to true.
91   -dc            Display debugging information for the compiler.
92   -dl            Display debugging information for the loader.
93   -debug         Launch the debugger.
94   -remote-debug  Run the program under the control of a remote debugger.
95   -e 'code'      Directly compile and execute code (no file provided).
96   -Idir1[:dir2]  Add directories to $LOAD_PATH.
97   -S script      Run script using PATH environment variable to find it.
98   -p             Run the profiler.
99   -ps            Run the Selector profiler.
100   -pss           Run the SendSite profiler.
101   -rlibrary      Require library before execution.
102   -w             Enable warnings. (currently does nothing--compatibility)
103   -v             Display the version and set $VERBOSE to true.
106 $VERBOSE = false
107 code = 0
109 show_selectors = false
110 show_sendsites = false
112 # Setup the proper staticscope
113 MethodContext.current.method.staticscope = StaticScope.new(Object)
115 TOPLEVEL_BINDING = binding()
117 eval_code = nil
118 script = nil
120 begin
121   script_debug_requested = false
122   until ARGV.empty?
123     arg = ARGV.shift
124     case arg
125     when '--'
126       break
127     when '-h', '--help'
128       puts RBS_USAGE
129       exit 1
130     when "-v"
131       puts "rubinius #{RBX_VERSION} (ruby #{RUBY_VERSION} compatible) (#{Rubinius::BUILDREV[0..8]}) (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
132       $VERBOSE = true
133       exit 0 if ARGV.empty?
134     when "-w"
135       # do nothing (HACK)
136     when '-dc'
137       puts "[Compiler debugging enabled]"
138       $DEBUG_COMPILER = true
139     when '-dl'
140       $DEBUG_LOADING = true
141       puts "[Code loading debugging enabled]"
142     when '-d'
143       $DEBUG = true
144     when '-debug'
145       require 'debugger/interface'
146       Debugger::CmdLineInterface.new
147       script_debug_requested = true
148     when '-remote-debug'
149       require 'debugger/debug_server'
150       if port = (ARGV.first =~ /^\d+$/ and ARGV.shift)
151         $DEBUG_SERVER = Debugger::Server.new(port.to_i)
152       else
153         $DEBUG_SERVER = Debugger::Server.new
154       end
155       $DEBUG_SERVER.listen
156       script_debug_requested = true
157     when '-p'
158       require 'profile'
159     when '-ps'
160       count = (ARGV.first =~ /^\d+$/) ? ARGV.shift : '30'
161       show_selectors = count.to_i
162     when '-pss'
163       count = (ARGV.first =~ /^\d+$/) ? ARGV.shift : '30'
164       show_sendsites = count.to_i
165     when '-S'
166       script = ARGV.shift
167       sep    = File::PATH_SEPARATOR
168       path   = ENV['PATH'].split(sep).map { |d| File.join(d, script) }
169       file   = path.find { |path| File.exist? path }
171       $0 = script if file
173       # if missing, let it die a natural death
174       ARGV.unshift file ? file : script
175     when '-e'
176       $0 = "(eval)"
177       eval_code = ARGV.shift
178     else
179       if arg.prefix? "-I"
180         more = arg[2..-1]
181         if more.empty?
182           $LOAD_PATH.unshift(ARGV.shift)
183         else
184           more.split(":").reverse_each do |path|
185             $LOAD_PATH.unshift(path)
186           end
187         end
188       elsif arg.prefix? "-r"
189         more = arg[2..-1]
190         if more.empty?
191           require ARGV.shift
192         else
193           require more
194         end
195       elsif arg == "-"
196         $0 = "-"
197         Compile.execute STDIN.read
198       elsif arg.prefix? "-"
199         puts "Invalid switch '#{arg}'"
200         puts RBS_USAGE
201         exit! 1
202       else
203         script = arg
204         # And we're done.
205         break
206       end
207     end
208   end
210   # If someone used -e, run that code.
211   if eval_code
212     # If we also caught a script to run, we just treat it like
213     # another arg.
214     ARGV.unshift script if script
216     Compile.execute eval_code
217   elsif script
218     if File.exists?(script)
219       $0 = script
220       Compile.debug_script! if script_debug_requested
221       Compile.load_from_extension arg 
222     else
223       if script.suffix?(".rb")
224         puts "Unable to find '#{script}'"
225         exit! 1
226       else
227         prog = File.join main_lib, "bin", script
228         if File.exists? prog
229           $0 = prog
230           load prog
231         else
232           raise LoadError, "Unable to find a script '#{script}' to run"
233         end
234       end
235     end
236   end
238   unless $0
239     if Rubinius::Terminal
240       repr = ENV['RBX_REPR'] || "bin/irb"
241       $0 = repr
242       prog = File.join main_lib, repr
243       begin
244         load prog
245       rescue LoadError => e
246         STDERR.puts "Unable to find repr named '#{repr}' to load."
247         exit 1
248       end
249     else
250       $0 = "(eval)"
251       Compile.execute "p #{STDIN.read}"
252     end
253   end
254   
255 rescue SystemExit => e
256   code = e.status
257 rescue Object => e
258   begin
259     if e.kind_of? Exception or e.kind_of? ThrownValue
260       msg = e.message
261     else
262       msg = "strange object detected as exception: #{e.inspect}"
263     end
264     if e.kind_of? SyntaxError
265       puts "A syntax error has occured:"
266       puts "    #{msg}"
267       puts "    near line #{e.file}:#{e.line}, column #{e.column}"
268       puts "\nCode:\n#{e.code}"
269       if e.column
270         puts((" " * (e.column - 1)) + "^")
271       end
272     else
273       puts "An exception has occurred:"
274       puts "    #{msg} (#{e.class})"
275     end
276     puts "\nBacktrace:"
277     puts e.awesome_backtrace.show
278     code = 1
279   rescue Object => e2
280     puts "Unable to build backtrace due to errors"
281     puts "Original Exception: #{e.inspect} (#{e.class})"
282     puts "New Exception: #{e2.inspect} (#{e.class})"
283     code = 128
284   end
287 begin
288   Rubinius::AtExit.shift.call until Rubinius::AtExit.empty?
289 rescue SystemExit => e
290   code = e.status
291 rescue Object => e
292   puts "An exception occurred inside an at_exit handler:"
293   puts "    #{e.message} (#{e.class})"
294   puts "\nBacktrace:"
295   puts e.awesome_backtrace.show
296   code = 1
299 begin
300   ObjectSpace.run_finalizers
301 rescue Object => e
302   puts "An exception occured while running object finalizers:"
303   puts "    #{e.message} (#{e.class})"
304   puts "\nBacktrace:"
305   puts e.awesome_backtrace.show
306   code = 1
309 if show_selectors
310   ps = Sampler::Selectors.new
311   begin
312     ps.show_stats show_selectors
313   rescue Object => e
314     puts "An exception occured while running selector profiler:"
315     puts "    #{e.message} (#{e.class})"
316     puts "\nBacktrace:"
317     puts e.awesome_backtrace.show
318     code = 1
319   end
322 if show_sendsites
323   ps = Sampler::SendSites.new
324   begin
325     ps.show_stats show_sendsites
326   rescue Object => e
327     puts "An exception occured while running sendsite profiler:"
328     puts "    #{e.message} (#{e.class})"
329     puts "\nBacktrace:"
330     puts e.awesome_backtrace.show
331     code = 1
332   end
335 Process.exit(code || 0)