## make-mythryld-executable.pkg
# Compiled by:
#
src/lib/core/internal/interactive-system.lib# Here we handle generation of a new compiler "executable"
# heap image, and also start-of-execution of that image, since our
# image generation primitive (lib7::fork_to_disk f) is like fork()
# in that it returns one value in the dumping process and another
# value in the dumped process.
#
# At image generation time (aka "link time") this code builds the boot
# dictionaries, sets default signal handlers, and then dumps a heap.
# When the heap image restarts, the system goes interactive.
#
# (We do not want to go interactive before dumping the heap because it
# would mean that dictionaries get loaded unnecessarily.)
#
# This code refers directly to package compiler, because by the time it
# gets compiled, Makelib's conditional compilation facility has already
# made sure that package compiler refers to the visible compiler
# for the current architecture.
### "If I had to do it over again?
### Hmmm...
### I guess I'd spell 'creat()' with an 'e'."
###
### -- Ken Thompson
# mythryl_compiler_compiler_configuration is from
src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-configuration.pkgstipulate
package at = run_at__premicrothread; # run_at__premicrothread is from
src/lib/std/src/nj/run-at--premicrothread.pkg package bc = basic_control; # basic_control is from
src/lib/compiler/front/basics/main/basic-control.pkg package ci = global_control_index; # global_control_index is from
src/lib/global-controls/global-control-index.pkg package cst = compile_statistics; # compile_statistics is from
src/lib/compiler/front/basics/stats/compile-statistics.pkg package ctl = global_controls; # global_controls is from
src/lib/compiler/toplevel/main/global-controls.pkg package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package iox = io_exceptions; # io_exceptions is from
src/lib/std/src/io/io-exceptions.pkg package is = interprocess_signals; # interprocess_signals is from
src/lib/std/src/nj/interprocess-signals.pkg package lms = list_mergesort; # list_mergesort is from
src/lib/src/list-mergesort.pkg package mcb = mythryl_compiler; # mythryl_compiler is from
src/lib/core/compiler/set-mythryl_compiler-to-mythryl_compiler_for_intel32_posix.pkg package mcc = makelib_internal::mythryl_compiler_compiler_configuration; # makelib_internal is from
src/lib/core/internal/makelib-internal.pkg package mce = make_mythryl_compiler_etc; # make_mythryl_compiler_etc is from
src/lib/core/internal/make-mythryl-compiler-etc.pkg package mcv = mythryl_compiler_version; # mythryl_compiler_version is from
src/lib/core/internal/mythryl-compiler-version.pkg package ri = runtime_internals; # runtime_internals is from
src/lib/std/src/nj/runtime-internals.pkg package wnx = winix__premicrothread; # winix__premicrothread is from
src/lib/std/winix--premicrothread.pkg package xns = exceptions; # exceptions is from
src/lib/std/exceptions.pkgherein
package make_mythryld_executable: (weak) api { } { # No return value -- our 'return value' is the 'mythryld' compiler executable heap image file we generate.
# file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg my _ = { # A little trick forcing all our code to execute immediately upon this module being loaded.
my { the_do_all_requested_compiles } # This is ultimately the return value from
= # fun read_''library_contents''_and_compile_''init_cmi''_and_preload_libraries'
mce::make_mythryl_compiler_etc # in
src/app/makelib/main/makelib-g.pkg
{
root_dir_of_mythryl_source_distro
=>
wnx::file::current_directory ()
}
# Can't we move this exception busywork down into mce:: ?
except
e as iox::IO { op, name, cause }
=>
{ fil::write (fil::stderr,
cat ["IO exception: file = ", name,
", op = ", op,
", cause: ",
xns::exception_message cause,
"\n"]);
raise exception e;
};
e
=>
{ fil::write (fil::stderr,
cat ["exception raised during init phase: ",
xns::exception_message e, "\n"]);
raise exception e;
};
end;
do_all_requested_compiles
=
# Can't we move this busywork down into mce:: ?
case the_do_all_requested_compiles # Ultimately, this is the return value from fun read_''library_contents''_and_compile_''init_cmi''_and_preload_libraries' in
src/app/makelib/main/makelib-g.pkg THE do_all_requested_compiles # Defined by "fun do_all_requested_compiles () ..." in
src/app/makelib/main/makelib-g.pkg =>
do_all_requested_compiles;
#
# Above does NOT RETURN!
NULL =>
raise exception DIE "make-mythryld-executable.pkg: the_do_all_requested_compiles was NULL?!\n";
esac;
# Establish default signal handlers:
#
fun handle_sigint _
=
*unsafe::sigint_fate; # unsafe is from
src/lib/std/src/unsafe/unsafe.pkg #
fun handle_term _
=
wnx::process::exit_x wnx::process::failure;
#
my _ =
{ is::override_signal_handler (is::SIGINT, is::HANDLER handle_sigint );
is::override_signal_handler (is::SIGTERM, is::HANDLER handle_term );
is::override_signal_handler (is::SIGQUIT, is::HANDLER handle_term );
};
# Install "read_eval_print_hook" functionality:
/* */ my _ =
read_eval_print_hook::read_eval_print_hook
:=
mcb::rpl::read_eval_print_from_file;
# Put lowhalf controls into the main hierarchy of controls:
/* */ my _ =
bc::note_subindex
(
ctl::lowhalf::prefix,
ctl::lowhalf::registry,
ctl::lowhalf::menu_slot
);
my _ =
{
# Initialize controls. In particular, this will
# (for example) initialize control cm::foo
# from the Unix environment variable CM_FOO,
# if it exists:
#
ci::set_up_controls_from_posix_environment
#
bc::top_index;
# Populate toplevel scripting enviroment with
# various handy things, in particular
#
# makelib::scripting_globals # See "package scripting_globals" def in
src/app/makelib/main/makelib-g.pkg #
stipulate
fun eval_string code_string
=
safely::do { # This should be a supported, exported 'eval' function.
#
open_it => {. fil::open_string code_string; },
close_it => fil::close_input,
cleanup => \\ _ = ()
}
mcb::rpl::read_eval_print_from_stream;
herein
# Empty the contents of the 'makelib' package
# into the toplevel environment, so we can
# interactively type
# help ()
# instead of the more verbose
# makelib::help ()
# and ditto for show_apis() etc.
my _ =
{ eval_string "include package makelib;;"; print "\n\n"; };
# Ditto for the 'math' package:
my _ =
{ eval_string "include package math;;"; print "\n\n"; };
# Ditto for the 'file' package:
my _ =
{ eval_string "include package file__premicrothread;;"; print "\n\n"; };
my _ =
{ eval_string "include package makelib::scripting_globals;;"; print "\n\n"; };
end;
{ ctl::print::say (" make-mythryld-executable.pkg: Startup/shutdown code-hooks schedule is:\n\n");
#
# Here we whip up a listing looking something like:
#
# ([ STARTUP_PHASE_4_MAKE_STDIN_STDOUT_AND_STDERR ], winix-text-file-for-os-g--premicrothread.pkg: Make stdin/stdout/stderr
# ([ STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS ], io-startup-and-shutdown--premicrothread.pkg: .init streams
# ([ STARTUP_PHASE_7_RESET_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE ], interprocess-signals.pkg: reset_posix_interprocess_signal_handler_table
# ([ STARTUP_PHASE_8_RESET_COMPILER_STATISTICS ], compile-statistics.pkg: reset
# ([ STARTUP_PHASE_9_RESET_CPU_AND_WALLCLOCK_TIMERS ], runtime-internals: reset cpu and wallclock timers
# ([ STARTUP_PHASE_11_START_SUPPORT_HOSTTHREADS ], microthread-preemptive-scheduler.pkg: start support hostthreads
# ([ STARTUP_PHASE_16_OF_HEAP_MADE_BY_SPAWN_TO_DISK ], interprocess-signals.pkg: initialize_posix_interprocess_signal_handler_table
# ([ SHUTDOWN_PHASE_4_STOP_SUPPORT_HOSTTHREADS ], microthread-preemptive-scheduler.pkg: stop support hostthreads
# ([ SHUTDOWN_PHASE_5_ZERO_COMPILE_STATISTICS ], compile-statistics.pkg: last := zeros
# ([ SHUTDOWN_PHASE_6_CLOSE_OPEN_FILES ], io-startup-and-shutdown--premicrothread.pkg: .close streams
# ([ SHUTDOWN_PHASE_6_FLUSH_OPEN_FILES ], io-startup-and-shutdown--premicrothread.pkg: .flush streams
# ([ SHUTDOWN_PHASE_7_CLEAR_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE ], interprocess-signals.pkg: clear_posix_interprocess_signal_handler_table
#
fun compare_schedule_entries ((_, (when1 ! _)), (_, (when2 ! _))) => at::when_gt (when1, when2);
compare_schedule_entries _ => TRUE; # Cannot happen.
end;
schedule = at::get_schedule();
schedule = lms::sort_list compare_schedule_entries schedule;
apply' schedule (\\ (label, whens) = printf " ([ %-66s ],\t %s\n" (string::join ", " (map at::when_to_string whens)) label);
};
ctl::print::say ("\n\n make-mythryld-executable.pkg: Generating heap image '" + mcc::mythryld_executable_filename_to_create + "'...\n");
# Now we do our 'fork-to-disk' call.
#
#
case (lib7::fork_to_disk mcc::mythryld_executable_filename_to_create) # fork_to_disk is from
src/lib/std/src/nj/save-heap-to-disk.pkg #
lib7::AM_CHILD
=>
{ # We are the dumped executable (heap image) # Note that at this point fork_to_disk will already have done
# just starting execution after #
# being invoked as an application, # at::run_functions_scheduled_to_run at::STARTUP_PHASE_[1-7]...
# and we need to go do our stuff: #
#
mythryld_app::main do_all_requested_compiles; # Does not return.
};
lib7::AM_PARENT
=>
{ # We are the 'parent' process generating
# the executable, and we're done:
#
print " make-mythryld-executable.pkg: Wrote executable for ";
print mcv::mythryl_interactive_banner;
print "\n";
print " make-mythryld-executable.pkg: Done, doing exit (0);\n";
wnx::process::exit_x wnx::process::success;
};
esac;
# read_eval_print_loops_g is from
src/lib/compiler/toplevel/interact/read-eval-print-loops-g.pkg # read_eval_print_loop_g is from
src/lib/compiler/toplevel/interact/read-eval-print-loop-g.pkg # translate_raw_syntax_to_execode_g is from
src/lib/compiler/toplevel/main/translate-raw-syntax-to-execode-g.pkg };
}; # my _ =
}; # package make_mythryld_executable
end; # stipulate