[project @ 1998-02-02 14:52:08 by simonm]
[ghc-hetmet.git] / ghc / driver / ghc.lprl
index 8629c83..92b6eee 100644 (file)
@@ -1,8 +1,5 @@
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
-%
-% *** MSUB does some substitutions here ***
-% *** grep for $( ***
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1997
 %
 
 This is the driver script for the Glasgow Haskell compilation system.
@@ -49,8 +46,8 @@ to stdout or stderr, however).
 
 The phase at which to STOP processing is determined by a command-line
 option:
+    -E         stop after generating preprocessed, de-litted Haskell (used in conjunction with -cpp)
     -C         stop after generating C (.hc output)
-    -E         stop after generating preprocessed C (.i output)
     -S         stop after generating assembler (.s output)
     -c         stop after generating object files (.o output)
 
@@ -65,18 +62,24 @@ Other commonly-used options are:
 
     -H14m      Increase compiler's heap size
 
+    -M          Output the Makefile rules recording the
+                dependencies of a list of Haskell files.
+               (ghc driver script calls upon the help of a
+                 compatible mkdependHS script to do the actual
+                processing)
+
 The User's Guide has more information about GHC's *many* options.
 
 Given the above, here are some TYPICAL invocations of $Pgm:
 
     # compile a Haskell module to a .o file, optimising:
     % $Pgm -c -O Foo.hs
+    # link three .o files into an executable called "test":
+    % $Pgm -o test Foo.o Bar.o Baz.o
     # compile a Haskell module to C (a .hc file), using a bigger heap:
     % $Pgm -C -H16m Foo.hs
     # compile Haskell-produced C (.hc) to assembly language:
     % $Pgm -S Foo.hc
-    # link three .o files into an executable called "test":
-    % $Pgm -o test Foo.o Bar.o Baz.o
 ------------------------------------------------------------------------
 EOUSAGE
 \end{code}
@@ -87,51 +90,54 @@ EOUSAGE
 %*                                                                     *
 %************************************************************************
 
-Establish what executables to run for the various phases (all the
-\tr{$(FOO)} make-variables are \tr{msub}bed for from the
-\tr{Makefile}), what the default options are for those phases, and
-other similar boring stuff.
-\begin{code}
-select(STDERR); $| = 1; select(STDOUT); # no STDERR buffering, please.
+The driver script need to be told where to find these executables, so
+in the course of building the driver `executable', make-variables holding
+these are prepended to the de-litted version of this file. The variables are:
 
-$HostPlatform   = '$(HOSTPLATFORM)';
-$TargetPlatform = '$(TARGETPLATFORM)';
+\begin{verbatim}
+INSTALLING
 
-#------------------------------------------------------------------------
-# If you are adjusting paths by hand for a binary GHC distribution,
-# de-commenting the line to set GLASGOW_HASKELL_ROOT should do.
-# Or you can leave it as is, and set the environment variable externally.
-#------------------------------------------------------------------------
-# $ENV{'GLASGOW_HASKELL_ROOT'} = '/some/absolute/path/name';
+HOSTPLATFORM TARGETPLATFORM
 
-if (! $ENV{'GLASGOW_HASKELL_ROOT'}) { # good -- death to environment variables
-    $TopPwd        = '$(TOP_PWD)';
-    $InstLibDirGhc  = '$(INSTLIBDIR_GHC)';
-    $InstDataDirGhc = '$(INSTDATADIR_GHC)';
-} else {
-    $TopPwd = $ENV{'GLASGOW_HASKELL_ROOT'};
+PROJECTNAME PROJECTVERSION PROJECTPATCHLEVEL
 
-    if ('$(INSTLIBDIR_GHC)' =~ /.*(\/lib\/ghc\/\d\.\d\d\/[^-]-[^-]-[^-]\/.*)/) {
-       $InstLibDirGhc  = $ENV{'GLASGOW_HASKELL_ROOT'} . $1;
-    } else {
-       print STDERR "GLASGOW_HASKELL_ROOT environment variable is set;\nBut can't untangle $(INSTLIBDIR_GHC).\n(Installation error)\n";
-       exit(1);
-    }
+TOP_PWD
 
-    if ('$(INSTDATADIR_GHC)' =~ /.*(\/lib\/ghc\/\d\.\d\d\/.*)/) {
-       $InstDataDirGhc = $ENV{'GLASGOW_HASKELL_ROOT'} . $2;
-    } else {
-       print STDERR "GLASGOW_HASKELL_ROOT environment variable is set;\nBut can't untangle $(INSTDATADIR_GHC).\n(Installation error)\n";
-       exit(1);
-    }
-}
+bindir libdir libexecdir datadir
 
-if ( $(INSTALLING) ) {
-    $InstSysLibDir  = $InstDataDirGhc;
-    $InstSysLibDir  =~ s/\/ghc\//\/hslibs\//;
-} else {
-    $InstSysLibDir  = "$TopPwd/hslibs";
-}
+CURRENT_DIR TMPDIR
+
+GHC_LIB_DIR GHC_RUNTIME_DIR GHC_UTILS_DIR GHC_INCLUDE_DIR
+
+GHC_OPT_HILEV_ASM GhcWithNativeCodeGen
+
+GHC_UNLIT GHC_HSCPP GHC_HSC GHC_SYSMAN
+
+CP RM CONTEXT_DIFF
+
+WAY_*_NAME WAY_*_HC_OPTS
+
+LeadingUnderscore
+
+\end{verbatim}
+
+Establish what executables to run for the various phases, what the
+default options are for those phases, and other similar boring stuff.
+
+\begin{code}
+select(STDERR); $| = 1; select(STDOUT); # no STDERR buffering, please.
+
+$TargetPlatform = $TARGETPLATFORM;
+
+$TopPwd                   = "${TOP_PWD}";
+$InstBinDirGhc     = "${bindir}";
+$InstLibDirGhc     = "${libdir}";
+#
+# Normally the same as InstLibDirGhc, but we accommodate
+# for it being separate.
+#
+$InstLibExecDirGhc = "${libexecdir}";
+$InstDataDirGhc    = "${datadir}";
 
 $Status  = 0; # just used for exit() status
 $Verbose = '';
@@ -143,70 +149,74 @@ $SIG{'QUIT'} = 'quit_upon_signal';
 
 # where to get "require"d .prl files at runtime (poor man's dynamic loading)
 #   (use LIB, not DATA, because we can't be sure of arch-independence)
-@INC = ( ( $(INSTALLING) ) ? $InstLibDirGhc
-                          : "$TopPwd/$(CURRENT_DIR)" );
+@INC = ( ( $INSTALLING ) ? $InstLibDirGhc
+                          : "$TopPwd/${CURRENT_DIR}" );
 
 if ( $ENV{'TMPDIR'} ) { # where to make tmp file names
     $Tmp_prefix = ($ENV{'TMPDIR'} . "/ghc$$");
 } else {
-    $Tmp_prefix ="$(TMPDIR)/ghc$$";
-    $ENV{'TMPDIR'} = '$(TMPDIR)'; # set the env var as well
+    print STDERR "TMPDIR has not been set to anything useful!\n" if (${TMPDIR} eq '');
+    $Tmp_prefix ="${TMPDIR}/ghc$$"; # TMPDIR set via Makefile when booting..
+    $ENV{'TMPDIR'} = ${TMPDIR}; # set the env var as well
+}
+
+# Some shells run into real trouble when command line and environment
+# gets big (e.g., cmd lines of >4K to /bin/sh causes havoc on our 
+# Solaris-2.5.1 boxes - even though sysconf(_SC_ARG_MAX) reports 1M ...).
+# To work around any such */bin/sh* problems, we will scribble such
+# awfully long command lines into a temp file and exec that temp file
+# with $(REAL_SHELL) (don't use the SHELL variable directly as this
+# will normally get you the wrong thing when the driver is invoked
+# from within `make'). If the REAL_SHELL variable isn't set, you'll
+# get SHELL. This is all a terrible hack. (in case you hadn't reached
+# the same conclusion by now :-)
+#
+# TBC..
+#
+if ( ! $ENV{'REAL_SHELL'} ) {
+    $ENV{'REAL_SHELL'} = $ENV{'SHELL'};
 }
 
 @Files_to_tidy = (); # files we nuke in the case of abnormal termination
 
-$Unlit = ( $(INSTALLING) ) ? "$InstLibDirGhc/unlit"
-                            : "$TopPwd/$(CURRENT_DIR)/$(GHC_UNLIT)";
+$Unlit = ( $INSTALLING ) ? "$InstLibExecDirGhc/unlit"
+                        : "$TopPwd/${CURRENT_DIR}/${GHC_UNLIT}";
 
-$Cp   = '$(CP)';
-$Rm   = '$(RM)';
-$Diff = '$(CONTEXT_DIFF)';
+$Cp   = $CP;
+$Rm   = $RM;
+$Diff = $CONTEXT_DIFF;
 $Cat  = 'cat';
 $Cmp  = 'cmp';
 $Time = '';
 
 $HsCpp  = # but this is re-set to "cat" (after options) if -cpp not seen
-          ( $(INSTALLING) ) ? "$InstLibDirGhc/hscpp"
-                            : "$TopPwd/$(CURRENT_DIR)/$(GHC_HSCPP)";
+          ( $INSTALLING ) ? "$InstLibExecDirGhc/hscpp"
+                          : "$TopPwd/${CURRENT_DIR}/${GHC_HSCPP}";
 
 @HsCpp_flags   = ();
 $genSPECS_flag = '';           # See ../utils/hscpp/hscpp.prl
-$HsC    = ( $(INSTALLING) ) ? "$InstLibDirGhc/hsc"
-                            : "$TopPwd/$(CURRENT_DIR)/$(GHC_HSC)";
+$HsC    = ( $INSTALLING ) ? "$InstLibExecDirGhc/hsc"
+                          : "$TopPwd/${CURRENT_DIR}/${GHC_HSC}";
 
 # For PVM fiends only
-$SysMan         = ( $(INSTALLING) ) ? "$InstLibDirGhc/SysMan"
-                            : "$TopPwd/$(CURRENT_DIR)/$(GHC_SYSMAN)";
-
+$SysMan         = ( $INSTALLING ) ? "$InstLibExecDirGhc/SysMan"
+                          : "$TopPwd/${CURRENT_DIR}/${GHC_SYSMAN}";
 
 @Unlit_flags   = ();
 
+#
 # HsC_rts_flags: if we want to talk to the LML runtime system
 # NB: we don't use powers-of-2 sizes, because this may do
 #   terrible things to cache behavior.
+#
 $Specific_heap_size = 6 * 1000 * 1000;
 $Specific_stk_size  = 1000 * 1000;
 $Scale_sizes_by     = 1.0;
-@HsC_rts_flags      = ();
-
-@HsP_flags     = (); # these are the flags destined solely for
-                     # the flex/yacc parser
-@HsC_flags     = ();
-@HsC_antiflags  = ();
-\end{code}
 
-The optimisations/etc to be done by the compiler are {\em normally}
-expressed with a \tr{-O} (or \tr{-O2}) flag, or by its absence.
-
-\begin{code}
-$OptLevel      = 0; # no -O == 0; -O == 1; -O2 == 2; -Ofile == 3
-$MinusO2ForC   = 0; # set to 1 if -O2 should be given to C compiler
-$StolenX86Regs = 4; # **HACK*** of the very worst sort
-$CoreLint      = '';
 \end{code}
 
-These variables represent parts of the -O/-O2/etc ``templates,''
-which are filled in later, using these.
+The variables set by @setupOptFlags@ represent parts of the
+-O/-O2/etc ``templates,'' which are filled in later, using these.
 These are the default values, which may be changed by user flags.
 
 \begin{code}
@@ -223,18 +233,24 @@ sub setupOptFlags {
    $Oopt_FB_Support              = ''; # was '-fdo-arity-expand';
 #  $Oopt_FoldrBuildWW            = 0; # Off by default
    $Oopt_FoldrBuildInline        = ''; # was '-fdo-inline-foldr-build';
+   $Oopt_ShowSimplifierProgress   = '';
 } # end of setupOptFlags
 
+# Assign defaults to these right away.
 &setupOptFlags();
 \end{code}
 
 Things to do with C compilers/etc:
 \begin{code}
-$CcRegd                = '$(GHC_OPT_HILEV_ASM)';
+$CcRegd                = $GHC_OPT_HILEV_ASM;
 @CcBoth_flags  = ('-S');   # flags for *any* C compilation
 @CcInjects     = ();
 
-# GCC flags: those for all files, those only for .c files; those only for .hc files
+# GCC flags: 
+#    those for all files, 
+#    those only for .c files;
+#    those only for .hc files
+
 @CcRegd_flags    = ('-ansi', '-D__STG_GCC_REGS__', '-D__STG_TAILJUMPS__');
 @CcRegd_flags_c        = ();
 @CcRegd_flags_hc = ();
@@ -250,209 +266,146 @@ $Lnkr           = ''; # "linker" is normally GCC
 $Nm = ($TargetPlatform =~ /^alpha-/) ? 'nm -B' : 'nm';
 \end{code}
 
+Warning packages that are controlled by -W and -Wall.  The 'standard'
+warnings that you get all the time are
+       
+       -fwarn-overlapping-patterns
+       -fwarn-missing-methods
+       -fwarn-duplicate-exports
+
+these are turned off by -Wnot.
+
+\begin{code}
+@StandardWarnings = ('-fwarn-overlapping-patterns', 
+                    '-fwarn-missing-methods',
+                    '-fwarn-duplicate-exports');
+@MinusWOpts              = (@StandardWarnings, 
+                    '-fwarn-incomplete-patterns', 
+                    '-fwarn-unused-binds',
+                    '-fwarn-unused-imports');
+@MinusWallOpts           = (@MinusWOpts, 
+                    '-fwarn-unused-matches',
+                    '-fwarn-name-shadowing');
+\end{code}
+
 What options \tr{-user-setup-a} turn into (user-defined ``packages''
+
 of options).  Note that a particular user-setup implies a particular
 Prelude ({\em including} its interface file(s)).
 \begin{code}
 $BuildTag      = ''; # default is sequential build w/ Appel-style GC
 
-%BuildAvail    = ('',      '$(Build_normal)',
-                  '_p',    '$(Build_p)',
-                  '_t',    '$(Build_t)',
-                  '_u',    '$(Build_u)',
-                  '_mc',   '$(Build_mc)',
-                  '_mr',   '$(Build_mr)',
-                  '_mt',   '$(Build_mt)',
-                  '_mp',   '$(Build_mp)',
-                  '_mg',   '$(Build_mg)',
-                  '_2s',   '$(Build_2s)',
-                  '_1s',   '$(Build_1s)',
-                  '_du',   '$(Build_du)',
-                  '_a',    '$(Build_a)',
-                  '_b',    '$(Build_b)',
-                  '_c',    '$(Build_c)',
-                  '_d',    '$(Build_d)',
-                  '_e',    '$(Build_e)',
-                  '_f',    '$(Build_f)',
-                  '_g',    '$(Build_g)',
-                  '_h',    '$(Build_h)',
-                  '_i',    '$(Build_i)',
-                  '_j',    '$(Build_j)',
-                  '_k',    '$(Build_k)',
-                  '_l',    '$(Build_l)',
-                  '_m',    '$(Build_m)',
-                  '_n',    '$(Build_n)',
-                  '_o',    '$(Build_o)',
-                  '_A',    '$(Build_A)',
-                  '_B',    '$(Build_B)' );
-
-%BuildDescr    = ('',      'normal sequential',
-                  '_p',    'profiling',
-                  '_t',    'ticky-ticky profiling',
-#OLD:             '_u',    'unregisterized (using portable C only)',
-                  '_mc',   'concurrent',
-                  '_mr',   'profiled concurrent',
-                  '_mt',   'ticky concurrent',
-                  '_mp',   'parallel',
-                  '_mg',   'GranSim',
-                  '_2s',   '2-space GC',
-                  '_1s',   '1-space GC',
-                  '_du',   'dual-mode GC',
-                  '_a',    'user way a',
-                  '_b',    'user way b',
-                  '_c',    'user way c',
-                  '_d',    'user way d',
-                  '_e',    'user way e',
-                  '_f',    'user way f',
-                  '_g',    'user way g',
-                  '_h',    'user way h',
-                  '_i',    'user way i',
-                  '_j',    'user way j',
-                  '_k',    'user way k',
-                  '_l',    'user way l',
-                  '_m',    'user way m',
-                  '_n',    'user way n',
-                  '_o',    'user way o',
-                  '_A',    'user way A',
-                  '_B',    'user way B' );
+%BuildDescr    = (# system ways begin
+                   '',     'normal sequential',
+                  '_p',    "$WAY_p_NAME",
+                  '_t',    "$WAY_t_NAME",
+                  '_u',    "$WAY_u_NAME",
+                  '_mc',   "$WAY_mc_NAME",
+                  '_mr',   "$WAY_mr_NAME",
+                  '_mt',   "$WAY_mt_NAME",
+                  '_mp',   "$WAY_mp_NAME",
+                  '_mg',   "$WAY_mg_NAME",
+                  '_2s',   "$WAY_2s_NAME",
+                  '_1s',   "$WAY_1s_NAME",
+                  '_du',   "$WAY_du_NAME",
+                  # system ways end
+                  '_a',    "$WAY_a_NAME",
+                  '_b',    "$WAY_b_NAME",
+                  '_c',    "$WAY_c_NAME",
+                  '_d',    "$WAY_d_NAME",
+                  '_e',    "$WAY_e_NAME",
+                  '_f',    "$WAY_f_NAME",
+                  '_g',    "$WAY_g_NAME",
+                  '_h',    "$WAY_h_NAME",
+                  '_i',    "$WAY_i_NAME",
+                  '_j',    "$WAY_j_NAME",
+                  '_k',    "$WAY_k_NAME",
+                  '_l',    "$WAY_l_NAME",
+                  '_m',    "$WAY_m_NAME",
+                  '_n',    "$WAY_n_NAME",
+                  '_o',    "$WAY_o_NAME",
+                  '_A',    "$WAY_A_NAME",
+                  '_B',    "$WAY_B_NAME" );
 
 # these are options that are "fed back" through the option processing loop
-%UserSetupOpts = ('_a', '$(GHC_BUILD_OPTS_a)',
-                  '_b', '$(GHC_BUILD_OPTS_b)',
-                  '_c', '$(GHC_BUILD_OPTS_c)',
-                  '_d', '$(GHC_BUILD_OPTS_d)',
-                  '_e', '$(GHC_BUILD_OPTS_e)',
-                  '_f', '$(GHC_BUILD_OPTS_f)',
-                  '_g', '$(GHC_BUILD_OPTS_g)',
-                  '_h', '$(GHC_BUILD_OPTS_h)',
-                  '_i', '$(GHC_BUILD_OPTS_i)',
-                  '_j', '$(GHC_BUILD_OPTS_j)',
-                  '_k', '$(GHC_BUILD_OPTS_k)',
-                  '_l', '$(GHC_BUILD_OPTS_l)',
-                  '_m', '$(GHC_BUILD_OPTS_m)',
-                  '_n', '$(GHC_BUILD_OPTS_n)',
-                  '_o', '$(GHC_BUILD_OPTS_o)',
-                  '_A', '$(GHC_BUILD_OPTS_A)',
-                  '_B', '$(GHC_BUILD_OPTS_B)',
-
-                  # the GC ones don't have any "fed back" options
-                  '_2s', '',
-                  '_1s', '',
-                  '_du', '' );
-
-# per-build code fragments which are eval'd
-%EvaldSetupOpts        = ('',      '', # this one must *not* be set!
-
-                           # profiled sequential
-                  '_p',    'push(@HsC_flags,  \'-fscc-profiling\');
-                            push(@CcBoth_flags, \'-DPROFILING\');',
-
-                           #and maybe ...
-                           #push(@CcBoth_flags, '-DPROFILING_DETAIL_COUNTS');
-
-                           # ticky-ticky sequential
-                  '_t',    'push(@HsC_flags, \'-fticky-ticky\');
-                            push(@CcBoth_flags, \'-DTICKY_TICKY\');',
-
-#OLD:                      # unregisterized (ToDo????)
-#                 '_u',    '',
-
-                           # concurrent
-                  '_mc',   '$StkChkByPageFaultOK = 0;
-                            push(@HsC_flags,  \'-fconcurrent\');
-                            push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');
-                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');',
-
-                           # profiled concurrent
-                  '_mr',   '$StkChkByPageFaultOK = 0;
-                            push(@HsC_flags,  \'-fconcurrent\', \'-fscc-profiling\');
-                            push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');
-                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DPROFILING\');',
-
-                           # ticky-ticky concurrent
-                  '_mt',   '$StkChkByPageFaultOK = 0;
-                            push(@HsC_flags,  \'-fconcurrent\', \'-fticky-ticky\');
-                            push(@HsCpp_flags,\'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\');
-                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DTICKY_TICKY\');',
-
-                           # parallel
-                  '_mp',   '$StkChkByPageFaultOK = 0;
-                            push(@HsC_flags,  \'-fconcurrent\');
-                            push(@HsCpp_flags,\'-D__PARALLEL_HASKELL__\',   \'-DPAR\');
-                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DPAR\');',
-
-                           # GranSim
-                  '_mg',   '$StkChkByPageFaultOK = 0;
-                            push(@HsC_flags,  \'-fconcurrent\', \'-fgransim\');
-                            push(@HsCpp_flags,\'-D__GRANSIM__\',   \'-DGRAN\');
-                            push(@Cpp_define, \'-D__CONCURRENT_HASKELL__\', \'-DCONCURRENT\', \'-DGRAN\');',
-
-                  '_2s',   'push (@CcBoth_flags, \'-DGC2s\');',
-                  '_1s',   'push (@CcBoth_flags, \'-DGC1s\');',
-                  '_du',   'push (@CcBoth_flags, \'-DGCdu\');',
-
-                  '_a',    '', # these user-way guys should not be set!
-                  '_b',    '',
-                  '_c',    '',
-                  '_d',    '',
-                  '_e',    '',
-                  '_f',    '',
-                  '_g',    '',
-                  '_h',    '',
-                  '_i',    '',
-                  '_j',    '',
-                  '_k',    '',
-                  '_l',    '',
-                  '_m',    '',
-                  '_n',    '',
-                  '_o',    '',
-                  '_A',    '',
-                  '_B',    '' );
+#
+%SetupOpts = 
+       (
+       '_a', "$WAY_a_HC_OPTS",
+       '_b', "$WAY_b_HC_OPTS",
+       '_c', "$WAY_c_HC_OPTS",
+       '_d', "$WAY_d_HC_OPTS",
+       '_e', "$WAY_e_HC_OPTS",
+       '_f', "$WAY_f_HC_OPTS",
+       '_g', "$WAY_g_HC_OPTS",
+       '_h', "$WAY_h_HC_OPTS",
+       '_i', "$WAY_i_HC_OPTS",
+       '_j', "$WAY_j_HC_OPTS",
+       '_k', "$WAY_k_HC_OPTS",
+       '_l', "$WAY_l_HC_OPTS",
+       '_m', "$WAY_m_HC_OPTS",
+       '_n', "$WAY_n_HC_OPTS",
+       '_o', "$WAY_o_HC_OPTS",
+       '_A', "$WAY_A_HC_OPTS",
+       '_B', "$WAY_B_HC_OPTS",
+
+       # system ways
+       '_p',  "$WAY_p_HC_OPTS",
+       '_t',  "$WAY_t_HC_OPTS",
+       '_u',  "$WAY_u_HC_OPTS",
+       '_mc', "$WAY_mc_HC_OPTS",
+       '_mr', "$WAY_mr_HC_OPTS",
+       '_mt', "$WAY_mt_HC_OPTS",
+       '_mp', "$WAY_mp_HC_OPTS",
+       '_mg', "$WAY_mg_HC_OPTS",
+       '_2s', "$WAY_2s_HC_OPTS",
+       '_1s', "$WAY_1s_HC_OPTS",
+       '_du', "$WAY_B_HC_OPTS" );
+
 \end{code}
 
 Import/include directories (\tr{-I} options) are sufficiently weird to
 require special handling.
+
 \begin{code}
 @Import_dir    = ('.'); #-i things
 @Include_dir   = ('.'); #-I things; other default(s) stuck on AFTER option processing
 
-@SysImport_dir = ( $(INSTALLING) )
-                   ? ( "$InstDataDirGhc/imports" )
-                   : ( "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/ghc"
-                     , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/glaExts"
-                     , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/required"
-                     , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/concurrent" );
+# where to look for interface files (system hi's, i.e., prelude and syslibs)
+@SysImport_dir = ( $INSTALLING )
+                   ? ( "$InstLibDirGhc/imports/std" )
+                   : ( "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/std" );
 
 # We need to look in ghc/ and glaExts/ when searching for implicitly needed .hi files, but 
 # we should really *not* look there for explicitly imported modules.
 
-$GhcVersionInfo  = int ($(PROJECTVERSION) * 100);
-$Haskell1Version = 3; # i.e., Haskell 1.3
+$GhcVersionInfo  = int($PROJECTVERSION * 100  + .5); # i.e., round (X.Y * 100)
+$Haskell1Version = 4; # i.e., Haskell 1.4
 @Cpp_define     = ();
 
 @UserLibrary_dir= ();  #-L things;...
 @UserLibrary           = ();   #-l things asked for by the user
 
-@SysLibrary_dir = ( ( $(INSTALLING) )  #-syslib things supplied by the system
+@SysLibrary_dir = ( ( $INSTALLING )    #-syslib things supplied by the system
                    ? $InstLibDirGhc
-                   : ( "$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)"
-                     , "$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)/gmp"
-                     , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)"
-                     , "$TopPwd/$(CURRENT_DIR)/$(GHC_LIBSRC)/cbits"
+                   : ( "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR"
+                     , "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/gmp"
+                     , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/std"
+                     , "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/std/cbits"
                      )
                  );
 @SysLibrary = (); # will be built up as we go along
 
 $TopClosureFile # defaults to 1.2 one; will be mangled later
-       = ( $(INSTALLING) ) ? "$InstLibDirGhc/TopClosureXXXX.o"
-                           : "$TopPwd/$(CURRENT_DIR)/$(GHC_RUNTIMESRC)/main/TopClosureXXXX.o";
+       = ( $INSTALLING)  ? "$InstLibDirGhc/TopClosureXXXX.o"
+                         : "$TopPwd/$CURRENT_DIR/$GHC_RUNTIME_DIR/main/TopClosureXXXX.o";
 
 # make depend for Haskell
 $MkDependHS
-       = ( $(INSTALLING) ) ? "$InstLibDirGhc/mkdependHS"
-                           : "$TopPwd/$(CURRENT_DIR)/$(GHC_UTILSRC)/mkdependHS/mkdependHS";
+       = ( $INSTALLING ) ? "$InstBinDirGhc/mkdependHS"
+                         : "$TopPwd/$CURRENT_DIR/$GHC_UTILS_DIR/mkdependHS/mkdependHS";
 # Fill in later
-@MkDependHS_flags = ( );
+@MkDependHS_flags = ();
 
 # do_link flag should not be reset while rescanning the cmd-line.
 $Do_lnkr    = 1;
@@ -473,14 +426,17 @@ sub initDriverGlobals {
                      # the flex/yacc parser
 @HsC_flags     = ();
 @HsC_antiflags  = ();
+\end{code}
+
+The optimisations/etc to be done by the compiler are {\em normally}
+expressed with a \tr{-O} (or \tr{-O2}) flag, or by its absence.
 
+\begin{code}
 $OptLevel      = 0; # no -O == 0; -O == 1; -O2 == 2; -Ofile == 3
 $MinusO2ForC   = 0; # set to 1 if -O2 should be given to C compiler
 $StolenX86Regs = 4; # **HACK*** of the very worst sort
 $CoreLint      = '';
-
-# reset flags used to guide the meaning of -O<level>
-&setupOptFlags();
+$StgLint       = '';
 
 @CcBoth_flags  = ('-S');   # flags for *any* C compilation
 @CcInjects     = ();
@@ -507,17 +463,20 @@ Here are the initial defaults applied to all files:
 \begin{code}
 $Cpp_flag_set = 0;       # (hack)
 $Only_preprocess_C = 0;          # pretty hackish
-$Only_generate_deps = 0;  #
+$Only_preprocess_hc = 0;  # ditto
+$Only_generate_deps = 0;  # "
 $PostprocessCcOutput = 0;
 
 # native code-gen or via C?
-$HaveNativeCodeGen = $(GhcWithNativeCodeGen);
+$HaveNativeCodeGen = $GhcWithNativeCodeGen;
 $HscOut = '-C='; # '-C=' ==> .hc output; '-S=' ==> .s output; '-N=' ==> neither
 $HscOut = '-S='
-    if $HaveNativeCodeGen && $TargetPlatform =~ /^(alpha|sparc)-/; #ToDo: add |i386 !
-$ProduceHi   = '-hifile=';
-$HiOnStdout  = 0;
-$HiDiff_flag = '';
+    if $HaveNativeCodeGen && $TargetPlatform =~ /^(alpha|sparc)-/;
+# TEMP: disable x86  if $HaveNativeCodeGen && $TargetPlatform =~ /^(i386|alpha|sparc)-/;
+$ProduceHi    = '-hifile=';
+$HiOnStdout   = 0;
+$HiDiff_flag  = '';
+$Keep_HiDiffs = 0;
 
 $CollectingGCstats = 0;
 $CollectGhcTimings = 0;
@@ -539,6 +498,7 @@ $Using_dump_file = 0;
 $Isuffix    = '';
 $Osuffix    = '';      # default: use the normal suffix for that kind of output
 $HiSuffix   = 'hi';
+$HiSuffix_prelude = '';
 $Do_recomp_chkr = 0;   # don't use the recompilatio checker unless asked
 $Do_cc     = -1;   # a MAGIC indeterminate value; will be set to 1 or 0.
 $Do_as     = 1;
@@ -567,6 +527,9 @@ $NoImplicitPrelude = 0;
 # and whatever else
 @Cmd_opts  = ();
 
+# cmd line options prefixing the unit we're compiling
+@File_options = ();
+
 \end{code}
 
 We inject consistency-checking information into \tr{.hc} files (both
@@ -581,10 +544,10 @@ $LinkChk = 1;     # set to 0 if the link check should *not* be done
 
 # major & minor version numbers; major numbers must always agree;
 # minor disagreements yield a warning.
-$HsC_major_version = 30;
+$HsC_major_version = 33;
 $HsC_minor_version = 0;
-$Cc_major_version  = 35;
-$Cc_minor_version  = 0;
+$Cc_major_version  = 36;
+$Cc_minor_version  = 1;
 
 # options: these must always agree
 $HsC_consist_options = '';    # we record, in this order:
@@ -602,37 +565,6 @@ $Cc_consist_options  = '';    # we record, in this order:
 Now slurp through the arguments.
 \begin{code}
 
-#---------- user defined prelude ---------------------------------------
-
-if (grep(/^-user-prelude$/, @ARGV)) {
-
-    # If ARGV contains -user-prelude we are compiling a piece of 
-    # prelude for the user, probably with additional specialise pragmas
-
-    # We strip out the -O -f and -user-prelude flags provided on
-    # the command line and add the ones used to compile the prelude
-    # ToDo: get these options from a common definition in mkworld
-
-    # We also enable any options forced through with -user-prelude-force
-
-    # Hey, Check out this grep statement ;-)  (PS)
-
-    @ARGV = grep((!/^-O/ && !/^-f/ && !/^-user-prelude$/) || s/^-user-prelude-force//,
-                @ARGV);
-
-    unshift(@ARGV,
-       '-fcompiling-ghc-internals=???', # ToDo!!!!
-        '-O',
-        '-fshow-pragma-name-errs',
-        '-fshow-import-specs',
-        '-fglasgow-exts',
-        '-genSPECS',
-        '-DUSE_FOLDR_BUILD',
-       '-dcore-lint');
-
-    print STDERR "ghc: -user-prelude options:\n", "@ARGV", "\n";
-}
-
 &initDriverGlobals();
 &splitCmdLine(@ARGV);
 # Run through the cmd-line first time.
@@ -644,6 +576,11 @@ if (  $Status == 0 && $Only_generate_deps ) {
 
     push (@MkDependHS_flags, "-o$Osuffix") if $Osuffix;
     push (@MkDependHS_flags, "-s$BuildTag") if $BuildTag;
+    push (@MkDependHS_flags, "-D__HASKELL1__=$Haskell1Version");
+    # They're not (currently) needed, but we need to quote any -#include options
+    foreach (@Cmd_opts) {
+       s/-#include.*$/'$&'/g;
+    };
     local($to_do) = "$MkDependHS @MkDependHS_flags -- @Cmd_opts -- @Input_file" ;
     &run_something($to_do, 'Haskell dependencies');
     exit $Status;
@@ -674,32 +611,6 @@ if ($Specific_output_dir ne '' && $Specific_output_file ne '') {
     }
 }
 
-# PROFILING stuff after argv mangling:
-if ( ! $PROFing ) {
-    # warn about any scc exprs found (in case scc used as identifier)
-    push(@HsP_flags, '-W');
-
-    # add -auto sccs even if not profiling !
-    push(@HsC_flags, $UNPROFscc_auto) if $UNPROFscc_auto;
-
-} else {
-    push(@HsC_flags, $PROFauto) if $PROFauto;
-    push(@HsC_flags, $PROFcaf)  if $PROFcaf;
-    #push(@HsC_flags, $PROFdict) if $PROFdict;
-
-    $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling';
-
-    push(@HsP_flags, (($PROFignore_scc) ? $PROFignore_scc : '-S'));
-
-    if ( $SplitObjFiles ) {
-       # can't split with cost centres -- would need global and externs
-       print STDERR "$Pgm: WARNING: splitting objects when profiling will *BREAK* if any _scc_s are present!\n";
-       # (but it's fine if there aren't any _scc_s around...)
-#      $SplitObjFiles = 0; # unset
-       #not an error: for now: $Status++;
-    }
-}
-
 # crash and burn if there were errors
 if ( $Status > 0 ) {
     print STDERR $ShortUsage;
@@ -774,22 +685,30 @@ sub setupOptimiseFlags {
 
    @HsC_minusNoO_flags 
     = (        '-fsimplify',
-         '\(',
+         '[',
          $Oopt_FB_Support,
-#        '-falways-float-lets-from-lets',      # no idea why this was here (WDP 95/09)
          '-ffloat-lets-exposing-whnf',
          '-ffloat-primops-ok',
          '-fcase-of-case',
+         '-fdo-case-elim',
 #        '-fdo-lambda-eta-expansion',  # too complicated
          '-freuse-con',
-#        '-flet-to-case',      # no strictness analysis, so...
+#        '-flet-to-case',              # no strictness analysis, so...
          $Oopt_PedanticBottoms,
 #        $Oopt_MonadEtaExpansion,      # no thanks
-         '-fsimpl-uf-use-threshold0',
-         '-fessential-unfoldings-only',
-#        $Oopt_UnfoldingUseThreshold,  # no thanks
+
+# These two work fine, if you really want no simplification at all,
+# for bizarre test reasons.  But you get really terrible code if you use them,
+#      for example: let x = e in x
+# with dozens of redundant thunks etc.  So I'm leaving them out.
+#
+#        '-fsimpl-uf-use-threshold0',
+#        '-fessential-unfoldings-only',
+
+         $Oopt_UnfoldingUseThreshold,
          $Oopt_MaxSimplifierIterations,
-         '\)',
+         $Oopt_ShowSimplifierProgress,
+         ']',
        $Oopt_AddAutoSccs,
 #      '-ffull-laziness',      # removed 95/04 WDP following Andr\'e's lead
        
@@ -802,14 +721,29 @@ sub setupOptimiseFlags {
 
        # initial simplify: mk specialiser happy: minimum effort please
        '-fsimplify',
-         '\(', 
+         '[', 
          $Oopt_FB_Support,
          '-fkeep-spec-pragma-ids',     # required before specialisation
-         '-fsimpl-uf-use-threshold0',
-         '-fessential-unfoldings-only',
+
+# I don't understand why we want -fessential-unfoldings-only here
+# If we have it, the following nasty thing happens:
+#      f  = E
+#      g* = f
+#      ...g...
+# where "*" means exported.
+# In the essential-unfoldings pass we still substitute f for g
+# but we don't substitute E for f first.  So we get
+#      f  = E
+#      g* = f
+#      ...f...
+# The g=f will get reverse-substituted later, but it's untidy.
+#
+#        '-fessential-unfoldings-only',
+#        '-fsimpl-uf-use-threshold0',
+
          '-fmax-simplifier-iterations1',
          $Oopt_PedanticBottoms,
-         '\)',
+         ']',
 
        ($Oopt_DoSpecialise) ? (
          '-fspecialise-overloaded',
@@ -818,7 +752,7 @@ sub setupOptimiseFlags {
        ) : (),
 
        '-fsimplify',                   # need dependency anal after specialiser ...
-         '\(',                         # need tossing before calc-inlinings ...
+         '[',                  # need tossing before calc-inlinings ...
          $Oopt_FB_Support,
          '-ffloat-lets-exposing-whnf',
          '-ffloat-primops-ok',
@@ -832,7 +766,8 @@ sub setupOptimiseFlags {
          $Oopt_MonadEtaExpansion,
          $Oopt_UnfoldingUseThreshold,
          $Oopt_MaxSimplifierIterations,
-         '\)',
+         $Oopt_ShowSimplifierProgress,
+         ']',
 
 #LATER:        '-fcalc-inlinings1', -- pointless for 2.01
 
@@ -840,7 +775,7 @@ sub setupOptimiseFlags {
 #              '-ffoldr-build-ww-anal',
 #              '-ffoldr-build-worker-wrapper',
 #              '-fsimplify', 
-#                '\(', 
+#                '[', 
 #                $Oopt_FB_Support,
 #                '-ffloat-lets-exposing-whnf',
 #                '-ffloat-primops-ok',
@@ -854,7 +789,8 @@ sub setupOptimiseFlags {
 #                $Oopt_MonadEtaExpansion,
 #                $Oopt_UnfoldingUseThreshold,
 #                $Oopt_MaxSimplifierIterations,
-#                '\)',
+#                $Oopt_ShowSimplifierProgress,
+#                ']',
 #       ) : (),
 
        # this pass-ordering sequence was agreed by Simon and Andr\'e
@@ -865,7 +801,7 @@ sub setupOptimiseFlags {
          '-ffoldr-build-on',           # desugar list comprehensions for foldr/build
 
          '-fsimplify', 
-           '\(', 
+           '[', 
            '-fignore-inline-pragma',   # **** NB!
            '-fdo-foldr-build',         # NB
            $Oopt_FB_Support,
@@ -881,13 +817,14 @@ sub setupOptimiseFlags {
            $Oopt_MonadEtaExpansion,
            $Oopt_UnfoldingUseThreshold,
            $Oopt_MaxSimplifierIterations,
-           '\)',
+           $Oopt_ShowSimplifierProgress,
+           ']',
        ) : (),
 
        '-ffloat-inwards',
 
        '-fsimplify',
-         '\(', 
+         '[', 
          $Oopt_FB_Support,
          '-ffloat-lets-exposing-whnf',
          '-ffloat-primops-ok',
@@ -905,12 +842,13 @@ sub setupOptimiseFlags {
          $Oopt_MonadEtaExpansion,
          $Oopt_UnfoldingUseThreshold,
          $Oopt_MaxSimplifierIterations,
-         '\)',
+         $Oopt_ShowSimplifierProgress,
+         ']',
 
        '-fstrictness',
 
        '-fsimplify',
-         '\(', 
+         '[', 
          $Oopt_FB_Support,
          '-ffloat-lets-exposing-whnf',
          '-ffloat-primops-ok',
@@ -925,7 +863,8 @@ sub setupOptimiseFlags {
          $Oopt_MonadEtaExpansion,
          $Oopt_UnfoldingUseThreshold,
          $Oopt_MaxSimplifierIterations,
-         '\)',
+         $Oopt_ShowSimplifierProgress,
+         ']',
 
        '-ffloat-inwards',
 
@@ -934,12 +873,12 @@ sub setupOptimiseFlags {
 
 #      ( ($OptLevel != 2)
 #        ? ''
-#      : "-fliberate-case -fsimplify \\( $Oopt_FB_Support -ffloat-lets-exposing-whnf -ffloat-primops-ok -fcase-of-case -fdo-case-elim -fcase-merge -fdo-eta-reduction -fdo-lambda-eta-expansion -freuse-con -flet-to-case $Oopt_PedanticBottoms $Oopt_MonadEtaExpansion $Oopt_UnfoldingUseThreshold $Oopt_MaxSimplifierIterations \\)" ),
+#      : "-fliberate-case -fsimplify [ $Oopt_FB_Support -ffloat-lets-exposing-whnf -ffloat-primops-ok -fcase-of-case -fdo-case-elim -fcase-merge -fdo-eta-reduction -fdo-lambda-eta-expansion -freuse-con -flet-to-case $Oopt_PedanticBottoms $Oopt_MonadEtaExpansion $Oopt_UnfoldingUseThreshold $Oopt_MaxSimplifierIterations $Oopt_ShowSimplifierProgress ]" ),
 
 # Final clean-up simplification:
 
        '-fsimplify',
-         '\(', 
+         '[', 
          $Oopt_FB_Support,
          '-ffloat-lets-exposing-whnf',
          '-ffloat-primops-ok',
@@ -958,7 +897,8 @@ sub setupOptimiseFlags {
          $Oopt_MonadEtaExpansion,
          $Oopt_UnfoldingUseThreshold,
          $Oopt_MaxSimplifierIterations,
-         '\)',
+         $Oopt_ShowSimplifierProgress,
+         ']',
 
       #        '-fstatic-args',
 
@@ -1005,6 +945,8 @@ if ( $OptLevel <= 0 ) {
 } else { # -Ofile, then...
 
     &add_Hsc_flags( @HsC_minusO3_flags );
+    push(@HsC_flags, $Oopt_FinalStgProfilingMassage) if $Oopt_FinalStgProfilingMassage;
+
     push(@CcBoth_flags, ($MinusO2ForC) ? '-O2' : '-O');        # possibly to be elaborated...
 }
 
@@ -1023,18 +965,47 @@ Sort out @$BuildTag@, @$PROFing@, @$CONCURing@, @$PARing@,
 \begin{code}
 sub setupBuildFlags {
 
-  if ( $BuildTag ne '' ) {
-      local($b) = $BuildDescr{$BuildTag};
-      if ($CONCURing eq 'c') { print STDERR "$Pgm: Can't mix $b with -concurrent.\n"; exit 1; }
-      if ($PARing    eq 'p') { print STDERR "$Pgm: Can't mix $b with -parallel.\n"; exit 1; }
-      if ($GRANing   eq 'g') { print STDERR "$Pgm: Can't mix $b with -gransim.\n"; exit 1; }
-      if ($TICKYing  eq 't') { print STDERR "$Pgm: Can't mix $b with -ticky.\n"; exit 1; }
 
-      # ok to have a user-way profiling build
-      # eval the profiling opts ... but leave user-way BuildTag 
-      if ($PROFing   eq 'p') { eval($EvaldSetupOpts{'_p'}); }
+   # PROFILING stuff after argv mangling:
+   if ( ! $PROFing ) {
+     # warn about any scc exprs found (in case scc used as identifier)
+     push(@HsP_flags, '-W');
+
+     # add -auto sccs even if not profiling !
+     push(@HsC_flags, $UNPROFscc_auto) if $UNPROFscc_auto;
+
+   } else {
+      push(@HsC_flags, $PROFauto) if $PROFauto;
+      push(@HsC_flags, $PROFcaf)  if $PROFcaf;
+      #push(@HsC_flags, $PROFdict) if $PROFdict;
+
+      $Oopt_FinalStgProfilingMassage = '-fmassage-stg-for-profiling';
+
+      # Ignore user sccs when auto annotating, but warn when doing so.
+      $PROFignore_scc = '-W' if $PROFauto; 
 
-  } elsif ( $PROFing eq 'p' ) {
+      push(@HsP_flags, (($PROFignore_scc) ? $PROFignore_scc : '-S'));
+
+      if ( $SplitObjFiles ) {
+        # can't split with cost centres -- would need global and externs
+        print STDERR "$Pgm: WARNING: splitting objects when profiling will *BREAK* if any _scc_s are present!\n";
+        # (but it's fine if there aren't any _scc_s around...)
+#       $SplitObjFiles = 0; # unset
+        #not an error: for now: $Status++;
+      }
+  }
+  #if ( $BuildTag ne '' ) {
+  #    local($b) = $BuildDescr{$BuildTag};
+  #    if ($CONCURing eq 'c') { print STDERR "$Pgm: Can't mix $b with -concurrent.\n"; exit 1; }
+  #    if ($PARing    eq 'p') { print STDERR "$Pgm: Can't mix $b with -parallel.\n"; exit 1; }
+  #    if ($GRANing   eq 'g') { print STDERR "$Pgm: Can't mix $b with -gransim.\n"; exit 1; }
+  #    if ($TICKYing  eq 't') { print STDERR "$Pgm: Can't mix $b with -ticky.\n"; exit 1; }
+
+  #    # ok to have a user-way profiling build
+  #    # eval the profiling opts ... but leave user-way BuildTag 
+  #    if ($PROFing   eq 'p') { &processArgs(split(' ', $SetupOpts{'_p'})); } # eval($EvaldSetupOpts{'_p'}); }
+
+  if ( $PROFing eq 'p' ) {
       if ($PARing   eq 'p') { print STDERR "$Pgm: Can't do profiling with -parallel.\n"; exit 1; }
       if ($GRANing  eq 'g') { print STDERR "$Pgm: Can't do profiling with -gransim.\n"; exit 1; }
       if ($TICKYing eq 't') { print STDERR "$Pgm: Can't do profiling with -ticky.\n"; exit 1; }
@@ -1071,21 +1042,33 @@ After the sanity checks, add flags to the necessary parts of the driver pipeline
 \begin{code}
   if ( $BuildTag ne '' ) { # something other than normal sequential...
 
-      local($Tag) = $BuildTag;  
+      local($Tag) = "${BuildTag}";
       $Tag =~ s/_//;  # move the underscore to the back
-      push(@HsP_flags, "-hisuf=.${Tag}_hi"); # use appropriate Prelude .hi files
 
       $HscOut = '-C='; # must go via C
-
-      eval($EvaldSetupOpts{$BuildTag});
+      &processArgs(split(' ', $SetupOpts{$BuildTag}));
+#      eval($EvaldSetupOpts{$BuildTag});
   }
 \end{code}
 
 Decide what the consistency-checking options are in force for this run:
 \begin{code}
+
   $HsC_consist_options = "${BuildTag},${DEBUGging}";
   $Cc_consist_options  = "${BuildTag},${DEBUGging}";
 
+  #
+  # Funny place to put it, but why not.
+  #
+  if ( $HiSuffix_prelude eq '' ) {
+       local($Tag) = "${BuildTag}";
+       $Tag =~ s/_//;
+       $Tag = "${Tag}_" if $Tag ne '';
+       $HiSuffix_prelude="${Tag}hi";
+  }
+  #push(@HsC_flags, "-hisuf-prelude=.${HiSuffix_prelude}"); # use appropriate Prelude .hi files
+  #push(@HsC_flags, "-hisuf=.${HiSuffix}");
+
 } # setupBuildFlags
 \end{code}
 
@@ -1114,10 +1097,14 @@ sub setupMachOpts {
       # we know how to *mangle* asm for hppa
       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
       unshift(@CcBoth_flags,  ('-static'));
+      #
       # We don't put in '-mlong-calls', because it's only
       # needed for very big modules (sigh), and we don't want
       # to hobble ourselves further on all the other modules
       # (most of them).
+      #  
+      # [Dated comment (gcc-2.6.x?), -mlong-calls is no longer
+      #  a supported gcc HPPA flag]
       unshift(@CcBoth_flags,  ('-D_HPUX_SOURCE'));
         # ___HPUX_SOURCE, not _HPUX_SOURCE, is #defined if -ansi!
         # (very nice, but too bad the HP /usr/include files don't agree.)
@@ -1125,7 +1112,10 @@ sub setupMachOpts {
   } elsif ($TargetPlatform =~ /^i386-/) {
       # we know how to *mangle* asm for X86
       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
-      unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
+      unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK && $TargetPlatform !~ /nextstep/;
+      # I do not know how to do STACK_CHECK_BY_PAGE_FAULT
+      # on NeXTs (my fault, not theirs), so I don't.
+      # CaS
 
       # -fno-defer-pop : basically the same game as for m68k
       #
@@ -1140,7 +1130,10 @@ sub setupMachOpts {
   } elsif ($TargetPlatform =~ /^m68k-/) {
       # we know how to *mangle* asm for m68k
       unshift (@CcRegd_flags, ('-D__STG_REV_TBLS__'));
-      unshift (@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
+      unshift (@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK && $TargetPlatform !~ /nextstep/;
+      # I do not know how to do STACK_CHECK_BY_PAGE_FAULT
+      # on NeXTs (my fault, not theirs), so I don't.
+      # CaS
 
       # -fno-defer-pop : for the .hc files, we want all the pushing/
       #    popping of args to routines to be explicit; if we let things
@@ -1163,13 +1156,12 @@ sub setupMachOpts {
       unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
       unshift(@CcBoth_flags,  ('-static'));
 
-  } elsif ($TargetPlatform =~ /^powerpc-/) {
+  } elsif ($TargetPlatform =~ /^powerpc-|^rs6000-/) {
       # we know how to *mangle* asm for PowerPC
-      unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
+# :-(   unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
       unshift(@CcRegd_flags, ('-DSTACK_CHECK_BY_PAGE_FAULT=1')) if $StkChkByPageFaultOK;
       unshift(@CcBoth_flags,  ('-static')); # always easier to start with
       unshift(@CcRegd_flags, ('-finhibit-size-directive')); # avoids traceback tables
-
   } elsif ($TargetPlatform =~ /^sparc-/) {
       # we know how to *mangle* asm for SPARC
       unshift(@CcRegd_flags, ('-D__STG_REV_TBLS__'));
@@ -1179,35 +1171,49 @@ sub setupMachOpts {
 } # end of setupMachOpts
 \end{code}
 
+%************************************************************************
+%*                                                                     *
+\subsection{Set up for warnings}
+%*                                                                     *
+%************************************************************************
+
+Several warnings are turned on by default.  These are supposed to be
+the 'I'm pretty sure you've made a mistake here' kind of warnings.
+The rest are turned on by the -W and -Wall options, or individually
+via their -fwarn and -fno-warn flags.
+
+\begin{code}
+sub setupWarningFlags {
+&add_Hsc_flags( @StandardWarnings );
+}
+\end{code}
+
 Same unshifting magic, but for special linker flags.
 
-Should really be whether or not we prepend underscores to global symbols,
-not an architecture test.  (JSM)
+The configure script determines whether the object file symbol tables
+have a leading underscore, and sets @LeadingUnderscore@ accordingly.
+(The driver script `sees' the setting of the @LeadingUnderscore@
+by having the Makefile prepend it).
 
 \begin{code}
 sub setupLinkOpts {
-  $Under = (   $TargetPlatform =~ /^alpha-/
-           || $TargetPlatform =~ /^hppa/
-           || $TargetPlatform =~ /^mips-sgi-irix/
-           || $TargetPlatform =~ /^powerpc-/
-           || $TargetPlatform =~ /-solaris/
-           || $TargetPlatform =~ /-linux$/
-          )
-          ? '' : '_';
+  local($uscore) = ( ${LeadingUnderscore} eq 'YES' ) ? '_' : '';
 
   unshift(@Ld_flags,
-        (($Ld_main) ? (
-          '-u', "${Under}Main_" . $Ld_main . '_closure',
-        ) : ()
-#         , '-u', "${Under}STbase_unsafePerformPrimIO_fast1"
-#         , '-u', "${Under}Prelude_Z91Z93_closure"      # i.e., []
-#         , '-u', "${Under}Prelude_IZh_static_info"
-#         , '-u', "${Under}Prelude_False_inregs_info"
-#         , '-u', "${Under}Prelude_True_inregs_info"
-#         , '-u', "${Under}Prelude_CZh_static_info"
-#         , '-u', "${Under}DEBUG_REGS"
-       ))
-         ; # just for fun, now...
+        (($Ld_main) ? ( '-u', "${uscore}Main_" . $Ld_main . '_closure' ) : ()));
+  unshift(@Ld_flags,
+       (  '-u', "${uscore}PrelBase_Z91Z93_closure"      # i.e., []
+          ,'-u', "${uscore}PrelBase_IZh_static_info"
+          ,'-u', "${uscore}PrelBase_CZh_static_info"
+          ,'-u', "${uscore}PrelBase_False_inregs_info"
+          ,'-u', "${uscore}PrelBase_True_inregs_info"
+          ,'-u', "${uscore}DEBUG_REGS"
+       ));
+  if ($TargetPlatform =~ /^powerpc-|^rs6000-/) {
+    # sometimes we have lots of toc entries...
+    #  unshift(@Ld_flags, ('-Xlinker -bbigtoc -Xlinker -bnoquiet')); 
+    unshift(@Ld_flags, ('-Xlinker -bbigtoc')); 
+  }
 
 } # end of setupLinkOpts
 
@@ -1226,11 +1232,11 @@ Ready for Business.
 \begin{code}
 sub setupIncPaths {
   # default includes must be added AFTER option processing
-  if ( ! $(INSTALLING) ) {
-      push (@Include_dir, "$TopPwd/$(CURRENT_DIR)/$(GHC_INCLUDESRC)");
+  if ( ! $INSTALLING ) {
+      push (@Include_dir, "$TopPwd/${CURRENT_DIR}/${GHC_INCLUDE_DIR}");
   } else {
       push (@Include_dir, "$InstLibDirGhc/includes");
-      push (@Include_dir, "$InstDataDirGhc/includes");
+      push (@Include_dir, "$InstLibDirGhc/includes");
   }
 } # end of setupIncPaths
 \end{code}
@@ -1251,7 +1257,12 @@ sub setupSyslibs {
   # Push library HSrts, plus boring clib bit
   push(@SysLibrary, "-lHSrts${BuildTag}");
   push(@SysLibrary, '-lHSclib');
-  push(@SysLibrary, '-lwinmm') if $BuildTag ne ''; # cygwin32 specific
+  #
+  # RTS compiled with cygwin32, uses the WinMM API
+  # to implement the itimers, since cygwin.dll does not
+  # support it. Only reqd. for `ways' that use itimers.
+  #
+  push(@SysLibrary, '-lwinmm') if $BuildTag ne '' && $TargetPlatform eq 'i386-unknown-cygwin32';
 
   # Push the pvm libraries
   if ($BuildTag eq '_mp') {
@@ -1278,9 +1289,9 @@ push(@SysLibrary, '-lm');
 Before continuing we check that the appropriate build is available.
 
 \begin{code}
-die "$Pgm: no BuildAvail?? $BuildTag\n" if ! $BuildAvail{$BuildTag}; # sanity
+#die "$Pgm: no BuildAvail?? $BuildTag\n" if $BuildDescr{$BuildTag} eq '' ; # sanity
 
-if ( $BuildAvail{$BuildTag} =~ /^NO$/ ) {
+if ( $BuildDescr{$BuildTag} eq '' ) {
     print STDERR "$Pgm: a `", $BuildDescr{$BuildTag},
        "' \"build\" is not available with your GHC setup.\n";
     print STDERR "(It was not configured for it at your site.)\n";
@@ -1317,8 +1328,8 @@ if ($#Input_file < 0 && $#Link_file < 0) {
     @Input_file = ( '-' );
 
     open(INF, "> $Tmp_prefix.hs") || &tidy_up_and_die(1,"Can't open $Tmp_prefix.hs\n");
-    print STDERR "Enter your Haskell program, end with ^D (on a line of its own):\n";
-    while (<>) { print INF $_; }
+    print STDERR "Enter your Haskell program, end with ^D (on a line of its own):\n" if -t;
+    while (<STDIN>) { print INF $_; }
     close(INF) || &tidy_up_and_die(1,"Failed writing to $Tmp_prefix.hs\n");
 }
 
@@ -1326,7 +1337,7 @@ if ($#Input_file < 0 && $#Link_file < 0) {
 
 Tell the world who we are, if they asked.
 \begin{code}
-print STDERR "$(PROJECTNAME), version $(PROJECTVERSION) $(PROJECTPATCHLEVEL)\n"
+print STDERR "${PROJECTNAME}, version ${PROJECTVERSION}, patchlevel ${PROJECTPATCHLEVEL}\n"
     if $Verbose;
 \end{code}
 
@@ -1349,7 +1360,8 @@ if ( $Status > 0 ) { # don't link if there were errors...
     exit $Status;
 }
 
-# append last minute flags linker flags (entry point)
+# append last minute flags linker and consistency flags
+&setupBuildFlags();
 &setupSyslibs();
 &setupLinkOpts();
 
@@ -1369,7 +1381,10 @@ if ($Do_lnkr) {
     local($lnkr) = ( $Lnkr ) ? $Lnkr : $CcRegd;
 
     local($output) = ($Specific_output_file ne '') ? "-o $Specific_output_file" : '';
-    @Files_to_tidy = ($Specific_output_file ne '') ? $Specific_output_file : 'a.out';
+    @Files_to_tidy = ($Specific_output_file ne '') ? 
+                     $Specific_output_file : 
+                     ( ($TargetPlatform eq 'i386-unknown-cygwin32') ? 'main.exe' : 'a.out');
+    print STDERR "Output file not specified, defaulting to \"main.exe\"\n" if ($Specific_output_file eq '' && $TargetPlatform eq 'i386-unknown-cygwin32');
 
     local($to_do) = "$lnkr $Verbose @Ld_flags $output @Link_file $TopClosureFile $libdirs @UserLibrary @SysLibrary";
     &run_something($to_do, 'Linker');
@@ -1412,10 +1427,11 @@ if ($Do_lnkr) {
        # OK, now create the magic script for "$executable"
        open(EXEC, "> $executable") || &tidy_up_and_die(1,"$Pgm: couldn't open $executable to write!\n");
        print EXEC <<EOSCRIPT1;
-#!$(PERL)
+eval 'exec perl -S \$0 \${1+"\$@"}'
+  if \$running_under_some_shell;
 # =!=!=!=!=!=!=!=!=!=!=!
 # This script is automatically generated: DO NOT EDIT!!!
-# Generated by Glasgow Haskell, version $(PROJECTVERSION) $(PROJECTPATCHLEVEL)
+# Generated by Glasgow Haskell, version ${PROJECTVERSION} ${PROJECTPATCHLEVEL}
 #
 \$pvm_executable      = '$pvm_executable';
 \$pvm_executable_base = '$pvm_executable_base';
@@ -1523,17 +1539,12 @@ Again, we'll do the post-recompilation-checker parts of this later.
     local($do_lit2pgm) = ($ifile =~ /\.lhs$/) ? 1 : 0;
     local($do_hscpp)   = 1; # but "hscpp" might really be "cat"
     local($do_hsc)     = 1;
-    local($do_cc)      = ( $Do_cc != -1) # i.e., it was set explicitly
-                         ? $Do_cc
-                         : ( ($HscOut eq '-C=') ? 1 : 0 );
-    local($do_as)      = $Do_as;
 
     # names of the files to stuff between phases
     # defaults are temporaries
     local($in_lit2pgm)   = $ifile;
     local($lit2pgm_hscpp) = "$Tmp_prefix.lpp";
     local($hscpp_hsc)    = "$Tmp_prefix.cpp";
-    local($hsc_out)      = ( $HscOut eq '-C=' ) ? "$Tmp_prefix.hc" : "$Tmp_prefix.s" ;
     local($hsc_hi)       = "$Tmp_prefix.hi";
     local($cc_as_o)      = "${Tmp_prefix}_o.s"; # temporary for raw .s file if opt C
     local($cc_as)        = "$Tmp_prefix.s";     # mangled or hsc-produced .s code
@@ -1541,59 +1552,85 @@ Again, we'll do the post-recompilation-checker parts of this later.
 
     local($is_hc_file) = 1; #Is the C code .hc or .c? Assume .hc for now
 
-    if ($ifile =~ /\.lhs$/) {
-       ; # nothing to change
-    } elsif ($ifile =~ /\.hs$/) {
-       $do_lit2pgm = 0;
-       $lit2pgm_hscpp = $ifile;
-    } elsif ($ifile =~ /\.hc$/ || $ifile =~ /_hc$/ ) { # || $ifile =~ /\.$Isuffix$/o) # ToDo: better
-       $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 1;
-       $hsc_out = $ifile;    
-    } elsif ($ifile =~ /\.c$/) {
-       $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 1;
-       $hsc_out = $ifile; $is_hc_file = 0;
-    } elsif ($ifile =~ /\.s$/) {
-       $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 0;
-       $cc_as = $ifile;    
-    } else { # don't know what it is, but nothing to do herein...
-       $do_lit2pgm = 0; $do_hscpp = 0; $do_hsc = 0; $do_cc = 0; $do_as = 0;
+    # OK, let's strip off some literate junk..
+    if ($do_lit2pgm) {
+        &runLit2pgm($in_lit2pgm, $lit2pgm_hscpp)
+    } else {
+        $lit2pgm_hscpp = $ifile;
     }
 
-    # OK, let's strip off some literate junk:
-    &runLit2pgm($in_lit2pgm, $lit2pgm_hscpp)
-       if $do_lit2pgm;
     #
     @File_options = ();
 
     # Scan the top of the de-litted file for {-# OPTIONS #-} pragmas
-    &check_for_source_options($lit2pgm_hscpp,*File_options);
-    # options found in the source file take a back seat, we will scan
+    &check_for_source_options($lit2pgm_hscpp,$ifile);
+
+    # Options found in the source file take a back seat, i.e., we scan
     # them first. Only process the command line again if source file
     # contained anything of interest *or* there's more than one
     # input file (we have to reset the options).
     #
-    if ( $#Input_file > 1 || $#File_options > 0) {
-        @File_options = (@File_options, @Cmd_opts);
+    if ( $#Input_file >= 0 || $#File_options >= 0) {
+        #@File_options = (@File_options, @Cmd_opts);
 
         # Now process the command line
-        &processArgs(@File_options);
+        &initDriverGlobals();
+        &processArgs((@File_options,@Cmd_opts));
+       print STDERR "\nEffective command line: " .
+                    join(' ',(@File_options,@Cmd_opts)) . "\n" if $Verbose;
     }
     #
     # Having got the effective command line scanned, set up
     # the various options in prep for some real work.
     #
-    &setupOptimiseFlags();
+    # check the sanity of the BuildTag we're about to use,
+    # and if needs be, add some more flags and setup to
+    # the different phases.
+    #
     &setupBuildFlags();
+    &setupOptimiseFlags();
     &setupMachOpts();
     &setupIncPaths();
+    &setupWarningFlags();
     &setupHeapStackSize();
 
+    #
+    # These two variables need to be set after the
+    # command-line has been processed and the build options
+    # have be seen set up. This is because command-line options
+    # can control whether to compile vias C or not.
+    # 
+    local($do_cc)      = ( $Do_cc != -1) # i.e., it was set explicitly
+                         ? $Do_cc
+                         : ( ($HscOut eq '-C=') ? 1 : 0 );
+    local($do_as)      = $Do_as;
+    local($hsc_out)      = ( $HscOut eq '-C=' ) ? "$Tmp_prefix.hc" : "$Tmp_prefix.s" ;
+
+    if ($Only_preprocess_hc) { # stop after having run $Cc -E
+       $do_as=0;
+    }
+    if ($Only_preprocess_C)     { # stop after having run $hscpp
+       $do_hsc=0; $do_cc = 0; $do_as=0;
+    } elsif ($ifile =~ /.lhs$/ || $ifile =~ /.hs$/ ) {
+       ;
+    } elsif ($ifile =~ /\.hc$/ || $ifile =~ /_hc$/ ) { # || $ifile =~ /\.$Isuffix$/o) # ToDo: better
+       $do_hscpp = 0; $do_hsc = 0; $do_cc = 1;
+       $hsc_out = $ifile;
+    } elsif ($ifile =~ /\.c$/) {
+       $do_hscpp = 0; $do_hsc = 0; $do_cc = 1;
+       $hsc_out = $ifile; $is_hc_file = 0;
+    } elsif ($ifile =~ /\.s$/) {
+       $do_hscpp = 0; $do_hsc = 0; $do_cc = 0;
+       $cc_as = $ifile;    
+    } else { # don't know what it is, but nothing to do herein...
+       $do_hscpp = 0; $do_hsc = 0; $do_cc = 0; $do_as = 0;
+    }
+
     # hack to avoid running hscpp
     $HsCpp = $Cat if ! $Cpp_flag_set;
 
-    &runHscpp($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc)
-       if $do_hscpp;
+    &runHscpp($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc) if $do_hscpp;
+
 \end{code}
 
 We now think about whether to run hsc/cc or not (when hsc produces .s
@@ -1602,9 +1639,18 @@ stuff, it effectively takes the place of both phases).
 To get the output file name right: for each phase that we are {\em
 not} going to run, set its input (i.e., the output of its preceding
 phase) to @"$ifile_root.<suffix>"@.
+
 \begin{code}
     local($going_interactive) = $HscOut eq '-N=' || $ifile_root eq '_stdin';
 
+    #
+    # Warning issued if -keep-hc-file-too is used without
+    # -fvia-C (or the equivalent)
+    #
+    if ( $HscOut ne '-C=' && $Keep_hc_file_too ) {
+       print STDERR "$Pgm: warning: Native code generator to be used, -keep-hc-file-too will be ignored\n";
+    }
+
     if (! $do_cc && ! $do_as) { # stopping after hsc
        $hsc_out = ($Specific_output_file ne '')
                 ? $Specific_output_file
@@ -1616,7 +1662,7 @@ phase) to @"$ifile_root.<suffix>"@.
     if (! $do_as) { # stopping after gcc (or hsc)
        $cc_as = ($Specific_output_file ne '')
                 ? $Specific_output_file
-                : &odir_ify($ifile_root, ( $Only_preprocess_C ) ? 'i' : 's');
+                : &odir_ify($ifile_root, ( $Only_preprocess_hc ) ? 'i' : 's');
 
        $ofile_target = $cc_as; # reset
     }
@@ -1634,11 +1680,13 @@ Now the Haskell compiler, C compiler, and assembler
 
     if ($do_cc) {
        &runGcc    ($is_hc_file, $hsc_out, $cc_as_o);
-       &runMangler($is_hc_file, $cc_as_o, $cc_as, $ifile_root);
+       &runMangler($is_hc_file, $cc_as_o, $cc_as, $ifile_root) if ! $Only_preprocess_hc;
     }
 
     &split_asm_file($cc_as)  if $do_as && $SplitObjFiles;
 
+    # save a copy of the .s file..
+    &saveIntermediate($ifile_root , "s" , $cc_as) if ($do_as && $Keep_s_file_too);
     &runAs($as_out, $ifile_root) if $do_as;
 \end{code}
 
@@ -1657,7 +1705,6 @@ Finally, decide what to queue up for linker input.
        pop(@Link_file); push(@Link_file, $ifile);
     }
 
-    &initDriverGlobals();
 
 } # end of ProcessInputFile
 \end{code}
@@ -1672,9 +1719,13 @@ Finally, decide what to queue up for linker input.
 sub runLit2pgm {
     local($in_lit2pgm, $lit2pgm_hscpp) = @_;
 
-    local($to_do) = "echo '#line 1 \"$in_lit2pgm\"' > $lit2pgm_hscpp && ".
-                   "$Unlit @Unlit_flags $in_lit2pgm -  >> $lit2pgm_hscpp";
-    @Files_to_tidy = ( $lit2pgm_hscpp );
+    local($to_do) = "";
+
+    # Only add #line pragma if we're going to need it.
+    $to_do  = "echo '#line 1 \"$in_lit2pgm\"' > $lit2pgm_hscpp && " if ($Cpp_flag_set);
+    $to_do .= "$Unlit @Unlit_flags $in_lit2pgm -  >> $lit2pgm_hscpp";
+     
+    push(@Files_to_tidy, $lit2pgm_hscpp );
 
     &run_something($to_do, 'literate pre-processor');
 }
@@ -1684,27 +1735,39 @@ sub runLit2pgm {
 sub runHscpp {
     local($in_lit2pgm, $lit2pgm_hscpp, $hscpp_hsc) = @_;
 
-    local($to_do);
+    local($to_do) = "";
+
+    # Strictly speaking, echoing of the following line pragma is only required
+    # on non-delit'ed input, as we've already added it during de-lit. However,
+    # hscpp will then add a {-# LINE 1 "$lit2pgm_hsc" -} to the top of the file,
+    # which is not very informative (but harmless). Hence, we uniformly have
+    # {-# LINE 1 "$in_lit2pgm" #-} as the first line to all cpp'ed hsc input.
+    #
+    $to_do = "echo '{-# LINE 1 \"$in_lit2pgm\" -}' > $hscpp_hsc && ";
 
     if ($HsCpp eq $Cat) {
-       $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ".
-                       "$HsCpp $lit2pgm_hscpp >> $hscpp_hsc";
-       @Files_to_tidy = ( $hscpp_hsc );
+       $to_do .= "$HsCpp $lit2pgm_hscpp >> $hscpp_hsc";
+       push(@Files_to_tidy, $hscpp_hsc );
        &run_something($to_do, 'Ineffective C pre-processor');
     } else {
        local($includes) = '-I' . join(' -I',@Include_dir);
-       $to_do = "echo '#line 1 \"$in_lit2pgm\"' > $hscpp_hsc && ".
-                       "$HsCpp $Verbose $genSPECS_flag @HsCpp_flags -D__HASKELL1__=$Haskell1Version -D__GLASGOW_HASKELL__=$GhcVersionInfo $includes $lit2pgm_hscpp >> $hscpp_hsc";
-       @Files_to_tidy = ( $hscpp_hsc );
+       $to_do .= "$HsCpp $Verbose $genSPECS_flag @HsCpp_flags -D__HASKELL1__=$Haskell1Version -D__GLASGOW_HASKELL__=$GhcVersionInfo $includes $lit2pgm_hscpp >> $hscpp_hsc";
+       push(@Files_to_tidy, $hscpp_hsc );
        &run_something($to_do, 'Haskellised C pre-processor');
     }
+   
+    if ( $Only_preprocess_C ) {
+       $to_do = "$Cat $hscpp_hsc";
+       &run_something($to_do, '');
+    }
+
 }
 \end{code}
 
 
 \begin{code}
 sub runHscAndProcessInterfaces {
-    local($ifile, $hscpp_hsc, $ifiel_root, $ofile_target, $hifile_target) = @_;
+    local($ifile, $hscpp_hsc, $ifile_root, $ofile_target, $hifile_target) = @_;
 
        # $ifile                is the original input file
        # $hscpp_hsc            post-unlit, post-cpp, etc., input file
@@ -1714,31 +1777,32 @@ sub runHscAndProcessInterfaces {
        
     local($source_unchanged) = 1;
 
-# Check if the source file is up to date relative to the target; in
-#  that case we say "source is unchanged" and let the compiler bale out
-# early if the import usage information allows it.
+    # Check if the source file is up to date relative to the target; in
+    # that case we say "source is unchanged" and let the compiler bail out
+    # early if the import usage information allows it.
 
     ($i_dev,$i_ino,$i_mode,$i_nlink,$i_uid,$i_gid,$i_rdev,$i_size,
      $i_atime,$i_mtime,$i_ctime,$i_blksize,$i_blocks) = stat($ifile);
 
-    if ( ! -f $ofile_target ) {
-       print STDERR "$Pgm:compile:Output file $ofile_target doesn't exist\n";
+    # The informational messages below are now conditional on -v being set -- SOF
+    if ( $ofile_target ne "_stdin.s" && ! -f $ofile_target ) {
+        print STDERR "$Pgm:compile:Output file $ofile_target doesn't exist\n" if $Verbose;
        $source_unchanged = 0;
     }
 
     ($o_dev,$o_ino,$o_mode,$o_nlink,$o_uid,$o_gid,$o_rdev,$o_size,
      $o_atime,$o_mtime,$o_ctime,$o_blksize,$o_blocks) = stat(_); # stat info from -f test
 
-    if ( ! -f $hifile_target ) {
-       print STDERR "$Pgm:compile:Interface file $hifile_target doesn't exist\n";
+    if ( $hifile_target ne "_stdout" && ! -f $hifile_target ) {
+        print STDERR "$Pgm:compile:Interface file $hifile_target doesn't exist\n" if $Verbose;
        $source_unchanged = 0;
     }
 
     ($hi_dev,$hi_ino,$hi_mode,$hi_nlink,$hi_uid,$hi_gid,$hi_rdev,$hi_size,
      $hi_atime,$hi_mtime,$hi_ctime,$hi_blksize,$hi_blocks) = stat(_); # stat info from -f test
 
-    if ($i_mtime > $o_mtime) {
-       print STDERR "$Pgm:recompile:Input file $ifile newer than $ofile_target\n";
+    if ( $ofile_target ne "_stdin.s" && $i_mtime > $o_mtime) {
+       print STDERR "$Pgm:recompile:Input file $ifile newer than $ofile_target\n" if $Verbose;
        $source_unchanged = 0;
     }
 
@@ -1748,24 +1812,39 @@ sub runHscAndProcessInterfaces {
        push(@HsC_flags, '-fsource-unchanged'); 
     }  
 
-# Run the compiler
+    # Run the compiler
 
     &runHsc($ifile_root, $hsc_out, $hsc_hi, $going_interactive);
 
-# See if it bailed out early, saying nothing needed doing.  
-# We work this out by seeing if it created an output .hi file
+   # See if it bailed out early, saying nothing needed doing.  
+   # We work this out by seeing if it created an output .hi file
 
-    if ( ! -f $hsc_hi ) {
+    if ( ! -f $hsc_hi && $ProduceHi !~ /-nohifile=/ ) {
        # Doesn't exist, so we bailed out early.
        # Tell the C compiler and assembler not to run
        $do_cc = 0; $do_as = 0;
 
-       # Update dependency info
-       &run_something("touch $ofile_target", "Touch $ofile_target, to propagate dependencies");
+       # Update dependency info, touch both object file and 
+       # interface file, so that the following invariant is
+        # maintained:
+       #
+       #   a dependent module's interface file should after recompilation
+        #   checking be newer than the interface files of its imports. 
+        #
+       # That is, if module A's interface file changes, then module B
+       # (which import from A) needs to be checked.
+        # If A's change does not affect B, which causes the compiler to bail
+       # out early, we still need to touch the interface file of B. The reason
+        # for this is that B may export A's interface.
+       #
+       &run_something("touch $ofile_target",
+                      "Touch $ofile_target,  to propagate dependencies") if $HscOut ne '-N=';
+       &run_something("touch $hifile_target", 
+                      "Touch $hifile_target,  to propagate dependencies") if $ProduceHi =~ /-nohifile=/ ;
 
     } else {   
 
-# Didn't bail out early (new .hi file) so we thunder on
+     # Didn't bail out early (new .hi file) so we thunder on
     
        # If non-interactive, heave in the consistency info at the end
        # NB: pretty hackish (depends on how $output is set)
@@ -1786,28 +1865,21 @@ sub runHscAndProcessInterfaces {
 
 
        # Interface-handling is important enough to live off by itself
-       require('ghc-iface.prl')
-           || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-iface.prl!\n");
-       
-       &postprocessHiFile($hsc_hi, $hifile_target, $going_interactive);
-       
-       # save a copy of the .hc file, even if we are carrying on...
-       if ($HscOut eq '-C=' && $do_cc && $Keep_hc_file_too) {
-           local($to_do) = "$Rm $ifile_root.hc; $Cp $hsc_out $ifile_root.hc";
-           &run_something($to_do, 'Saving copy of .hc file');
+        if ( $ProduceHi !~ /-nohifile=/ ) { # If we've produced one, process it.
+          require('ghc-iface.prl') || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-iface.prl!\n");
+          &postprocessHiFile($hsc_hi, $hifile_target, $going_interactive);
        }
-       
-       # save a copy of the .s file, even if we are carrying on...
-       if ($HscOut eq '-S=' && $do_as && $Keep_s_file_too) {
-           local($to_do) = "$Rm $ifile_root.s; $Cp $hsc_out $ifile_root.s";
-           &run_something($to_do, 'Saving copy of .s file');
-       }
-       
        # if we're going to split up object files,
        # we inject split markers into the .hc file now
        if ( $HscOut eq '-C=' && $SplitObjFiles ) {
            &inject_split_markers ( $hsc_out );
         }
+
+       # save a copy of the .hc file, even if we are carrying on...
+       if ($HscOut eq '-C=' && $do_cc && $Keep_hc_file_too) {
+            &saveIntermediate($ifile_root , "hc" , $hsc_out);
+       }
+
     }
 }
 \end{code}
@@ -1821,13 +1893,12 @@ sub runHsc {
     foreach $a ( @HsP_flags ) { $a = ",$a" unless $a =~ /^,/; }
 
     &makeHiMap() unless $HiMapDone;
-#    print STDERR "HiIncludes: $HiIncludeString\n";
+    #print STDERR "HiIncludes: $HiIncludeString\n";
     push(@HsC_flags, "-himap=$HiIncludeString");
-#    push(@HsC_flags, "-himap=$HiMapFile");
 
     # here, we may produce .hc/.s and/or .hi files
     local($output) = '';
-    @Files_to_tidy = ();
+    #@Files_to_tidy = ();
 
     if ( $going_interactive ) {
        # don't need .hi unless going to show it on stdout:
@@ -1838,7 +1909,7 @@ sub runHsc {
     # set up for producing output/.hi; note that flag twiddling
     # may mean that nothing will actually be produced:
     $output = "$ProduceHi$hsc_hi $HscOut$hsc_out";
-    @Files_to_tidy = ( $hsc_hi, $hsc_out );
+    push(@Files_to_tidy, $hsc_hi, $hsc_out );
 
     # if we're compiling foo.hs, we want the GC stats to end up in foo.stat
     if ( $CollectingGCstats ) {
@@ -1849,6 +1920,7 @@ sub runHsc {
     if ( $CollectGhcTimings ) { # assume $RTS_style eq 'ghc'
        # emit nofibbish time/bytes-alloc stats to stderr;
        # see later .stat file post-processing
+       print STDERR "warning: both -Rgc-stats and -Rghc-timing used, -Rghc-timing wins." if $CollectingGCstats;
        push(@HsC_rts_flags, "-s$Tmp_prefix.stat");
        push(@Files_to_tidy, "$Tmp_prefix.stat");
     }
@@ -1860,7 +1932,7 @@ sub runHsc {
     }
 
     local($to_do);
-    $to_do = "$HsC @HsP_flags ,$hscpp_hsc $dump @HsC_flags $CoreLint $Verbose $output +RTS @HsC_rts_flags";
+    $to_do = "$HsC @HsP_flags ,$hscpp_hsc $dump @HsC_flags $CoreLint $StgLint $Verbose $output +RTS @HsC_rts_flags";
     &run_something($to_do, 'Haskell compiler');
 
     # finish business w/ nofibbish time/bytes-alloc stats
@@ -1871,9 +1943,7 @@ sub runHsc {
 Use \tr{@Import_dir} and \tr{@SysImport_dir} to make a tmp file
 of (module-name, pathname) pairs, one per line, separated by a space.
 \begin{code}
-%HiMap     = ();
 $HiMapDone = 0;
-$HiMapFile = '';
 $HiIncludeString = ();         # dir1:dir2:dir3, to pass to GHC
 
 sub makeHiMap {
@@ -1883,81 +1953,29 @@ sub makeHiMap {
     local($mod, $path, $d, $e);
 
     # reset the global variables:
-    %HiMap     = ();
     $HiMapDone = 0;
-    $HiMapFile = '';
     $HiIncludeString = ();             # dir1:dir2:dir3, to pass to GHC
     
     foreach $d ( @Import_dir ) {
-       if ($HiIncludeString) { $HiIncludeString = "$HiIncludeString:$d";
-       } else { $HiIncludeString = $d; }
-
-       opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n");
-       local(@entry) = readdir(DIR);
-       foreach $e ( @entry ) {
-           next unless $e =~ /\b([A-Z][A-Za-z0-9_]*)\.$HiSuffix$/o;
-           $mod  = $1;
-           $path = "$d/$e";
-           $path =~ s,^\./,,;
-
-           if ( ! defined($HiMap{$mod}) ) {
-               $HiMap{$mod} = $path;
-           } else {
-               &already_mapped_err($mod, $HiMap{$mod}, $path);
-           }
+       if ($HiIncludeString) { 
+          $HiIncludeString = "$HiIncludeString:${d}%.${HiSuffix}";
+       } else { 
+          $HiIncludeString = "$d%.${HiSuffix}"; 
        }
-       closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n");
-    }
 
-    foreach $d ( @SysImport_dir ) {
-       if ($HiIncludeString) { $HiIncludeString = "$HiIncludeString:$d";
-       } else { $HiIncludeString = $d; }
-
-       opendir(DIR, $d) || &tidy_up_and_die(1,"$Pgm: error when reading directory: $d\n");
-       local(@entry) = readdir(DIR);
-       foreach $e ( @entry ) {
-           next unless $e =~ /([A-Z][A-Za-z0-9_]*)\.$HiSuffix$/o;
-           next if $NoImplicitPrelude && $e =~ /Prelude\.$HiSuffix$/o;
-
-           $mod  = $1;
-           $path = "$d/$e";
-           $path =~ s,^\./,,;
-
-           if ( ! defined($HiMap{$mod}) ) {
-               $HiMap{$mod} = $path;
-           } elsif ( $mod ne 'Main' )  { # saves useless warnings...
-               &already_mapped_err($mod, $HiMap{$mod}, $path);
-           }
-       }
-       closedir(DIR); # || &tidy_up_and_die(1,"$Pgm: error when closing directory: $d\n");
     }
 
-    $HiMapFile = "$Tmp_prefix.himap";
-    unlink($HiMapFile);
-    open(HIMAP, "> $HiMapFile") || &tidy_up_and_die(1,"$Pgm: can't open $HiMapFile\n");
-    foreach $d (keys %HiMap) {
-       print HIMAP $d, ' ', $HiMap{$d}, "\n";
+    foreach $d ( @SysImport_dir ) {
+       if ($HiIncludeString) { 
+           $HiIncludeString = "$HiIncludeString:${d}%.${HiSuffix_prelude}";
+       } else { 
+           $HiIncludeString = "${d}%.${HiSuffix_prelude}";
+        }
     }
-    close(HIMAP) || &tidy_up_and_die(1,"$Pgm: error when closing $HiMapFile\n");
 
     $HiMapDone = 1;
 }
 
-sub already_mapped_err {
-    local($mod, $mapped_to, $path) = @_;
-
-    # OK, it isn't really an error if $mapped_to and $path turn
-    # out to be the same thing.
-    ($m_dev,$m_ino,$m_mode,$m_nlink,$m_uid,$m_gid,$m_rdev,$m_size,
-     $m_atime,$m_mtime,$m_ctime,$m_blksize,$m_blocks) = stat($mapped_to);
-    ($p_dev,$p_ino,$p_mode,$p_nlink,$p_uid,$p_gid,$p_rdev,$p_size,
-     $p_atime,$p_mtime,$p_ctime,$p_blksize,$p_blocks) = stat($path);
-
-    return if $m_ino == $p_ino; # same inode number
-
-    print STDERR "$Pgm: module $mod already mapped to $mapped_to";
-    print STDERR ";\n\tignoring: $path\n";
-}
 \end{code}
 
 %************************************************************************
@@ -2007,7 +2025,7 @@ sub runGcc {
     local($cc_help_s) = "ghc$$.s";
 
     $cc       = $CcRegd;
-    $s_output = ($is_hc_file || $TargetPlatform =~ /^(hppa|i386)/) ? $cc_as_o : $cc_as;
+    $s_output = ($is_hc_file || $TargetPlatform =~ /^(powerpc|rs6000|hppa|i386)/) ? $cc_as_o : $cc_as;
     $c_flags .= " @CcRegd_flags";
     $c_flags .= ($is_hc_file) ? " @CcRegd_flags_hc"  : " @CcRegd_flags_c";
 
@@ -2033,15 +2051,21 @@ EOINCL
     print TMP "#include \"$hsc_out\"\n";
     close(TMP) || &tidy_up_and_die(1,"Failed writing to $cc_help\n");
 
-    local($to_do) = "$cc $Verbose $ddebug_flag $c_flags @Cpp_define -D__HASKELL1__=$Haskell1Version $includes $cc_help > $Tmp_prefix.ccout 2>&1 && ( if [ $cc_help_s != $s_output ] ; then mv $cc_help_s $s_output ; else exit 0 ; fi )";
+    # Don't redirect stderr into intermediate file if slamming output onto stdout (e.g., with -E)
+    local($fuse_stderr) = "2>&1" if ! $Only_preprocess_hc;
+    local($to_do) = "$cc $Verbose $ddebug_flag $c_flags @Cpp_define -D__HASKELL1__=$Haskell1Version $includes $cc_help > $Tmp_prefix.ccout $fuse_stderr && ( if [ $cc_help_s != $s_output ] ; then mv $cc_help_s $s_output ; else exit 0 ; fi )";
     # note: __GLASGOW_HASKELL__ is pointedly *not* #defined at the C level.
-    if ( $Only_preprocess_C ) { # HACK ALERT!
+
+    if ( $Only_preprocess_hc ) { # HACK ALERT!
        $to_do =~ s/ -S\b//g;
     }
-    @Files_to_tidy = ( $cc_help, $cc_help_s, $s_output );
-    $PostprocessCcOutput = 1;  # hack, dear hack...
+    push(@Files_to_tidy, $cc_help, $cc_help_s, $s_output );
+    $PostprocessCcOutput = 1 if ! $Only_preprocess_hc; # hack, dear hack...
     &run_something($to_do, 'C compiler');
     $PostprocessCcOutput = 0;
+    if ( $Only_preprocess_hc ) {
+       system("$Cat $Tmp_prefix.ccout");
+    }
     unlink($cc_help, $cc_help_s);
 }
 \end{code}
@@ -2062,6 +2086,7 @@ sub runMangler {
        # post-process the assembler [.hc files only]
        &mangle_asm($cc_as_o, $cc_as);
 
+
 #OLD: for sanity:
 #OLD:  local($target) = 'oops';
 #OLD:  $target = '-alpha'      if $TargetPlatform =~ /^alpha-/;
@@ -2087,6 +2112,11 @@ sub runMangler {
        || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-hppa.prl!\n");
        &mini_mangle_asm_hppa($cc_as_o, $cc_as);
 
+    } elsif ($TargetPlatform =~ /^powerpc|^rs6000/) {
+       # minor mangling of non-threaded files for powerpcs and rs6000s 
+       require('ghc-asm.prl')
+       || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-asm-powerpc.prl!\n");
+       &mini_mangle_asm_powerpc($cc_as_o, $cc_as);
     } elsif ($TargetPlatform =~ /^i386/) {
        # extremely-minor OFFENSIVE mangling of non-threaded just one file
        require('ghc-asm.prl')
@@ -2095,10 +2125,9 @@ sub runMangler {
     }
 
     # save a copy of the .s file, even if we are carrying on...
-    if ($do_as && $Keep_s_file_too) {
-       local($to_do) = "$Rm $ifile_root.s; $Cp $cc_as $ifile_root.s";
-       &run_something($to_do, 'Saving copy of .s file');
-    }
+    #if ($do_as && $Keep_s_file_too) {
+    #    &saveIntermediate($ifile_root , "s" , $cc_as);
+    #}
 }
 \end{code}
 
@@ -2110,17 +2139,27 @@ sub runAs {
 
     if ( ! $SplitObjFiles ) {
        local($to_do)  = "$asmblr -o $as_out -c @As_flags $cc_as";
-       @Files_to_tidy = ( $as_out );
+       push(@Files_to_tidy, $as_out );
        &run_something($to_do, 'Unix assembler');
 
     } else { # more complicated split-ification...
 
        # must assemble files $Tmp_prefix__[1 .. $NoOfSplitFiles].s
 
+        # If -odir is used, great, just pin it in front of the
+       # generated split file names. If it hasn't been set, we
+       # snatch it from the ifile_root.
+       #
+       # 
+
+        if ( $Specific_output_dir eq '' ) {
+            $Specific_output_dir = ${ifile_root};
+        }
+
        for ($f = 1; $f <= $NoOfSplitFiles; $f++ ) {
            local($split_out) = &odir_ify("${ifile_root}__${f}",'o');
            local($to_do) = "$asmblr -o $split_out -c @As_flags ${Tmp_prefix}__${f}.s";
-           @Files_to_tidy = ( $split_out );
+           push(@Files_to_tidy, $split_out );
 
            &run_something($to_do, 'Unix assembler');
        }
@@ -2150,8 +2189,29 @@ sub run_something {
     }
 
     local($return_val) = 0;
-    system("$Time $str_to_do");
-    $return_val = $?;
+
+    if ( length($str_to_do) > 4000) { 
+      # 4000 - on the random side, just like the *real* ARG_MAX 
+      # for some shells.
+
+      # With some shells, command lines of this length may
+      # very well cause trouble. To safeguard against this, we squirrel the
+      # command into a file and exec that.
+      local ($sh) = $ENV{'REAL_SHELL'};
+      print STDERR "Backup plan A: saving cmd line in ${Tmp_prefix}.sh and executing that with $sh\n" if $Verbose;
+      open (TEMP, "> ${Tmp_prefix}.sh") || 
+               &tidy_up_and_die(1,"$Pgm: failed to open `$Tmp_prefix.sh'\n");
+      print TEMP "$Time $str_to_do\n";
+      close (TEMP) ||
+               &tidy_up_and_die(1,"$Pgm: failed closing `$Tmp_prefix.sh'\n");
+      system("$sh $Tmp_prefix.sh");
+      $return_val = $?;
+      
+      unlink "${Tmp_prefix}.sh";
+    } else {
+      system("$Time $str_to_do");
+      $return_val = $?;
+    }
 
     if ( $PostprocessCcOutput ) { # hack, continued
        open(CCOUT, "< $Tmp_prefix.ccout")
@@ -2188,7 +2248,7 @@ sub run_something {
 
 %************************************************************************
 %*                                                                     *
-\subsection[Driver-ghctiming]{Emit nofibbish GHC timings}
+\subsection[Driver-ghc-timing]{Emit nofibbish GHC timings}
 %*                                                                     *
 %************************************************************************
 
@@ -2200,20 +2260,27 @@ sub process_ghc_timings {
     local($SysSpecificTiming) = 'ghc';
 
     open(STATS, $StatsFile) || die "Failed when opening $StatsFile\n";
-    local($tot_live) = 0; # for calculating avg residency
+    local($max_live)    = 0; 
+    local($tot_live)    = 0; # for calculating residency stuff
+    local($tot_samples) = 0;
 
     while (<STATS>) {
-       $tot_live += $1 if /^\s*\d+\s+\d+\s+\d+\.\d+\%\s+(\d+)\s+\d+\.\d+\%/;
-
-       $BytesAlloc = $1 if /^\s*([0-9,]+) bytes allocated in the heap/;
+       if (! /Minor/ && /^\s*\d+\s+\d+\s+(\d+)\s+\d+\.\d+\%/ ) {
+               $max_live = $1 if $max_live < $1;
+               $tot_live += $1;
+               $tot_samples += 1;
+       }
+        $BytesAlloc = $1 if /^\s*([0-9,]+) bytes allocated in the heap/;
 
        if ( /^\s*([0-9,]+) bytes maximum residency .* (\d+) sample/ ) {
            $MaxResidency = $1; $ResidencySamples = $2;
        }
 
-       $GCs = $1 if /^\s*([0-9,]+) garbage collections? performed/;
+        $GCs = $1 if /^\s*([0-9,]+) garbage collections? performed/;
 
-       if ( /^\s*INIT\s+time\s*(\d+\.\d\d)s\s*\(\s*(\d+\.\d\d)s elapsed\)/ ) {
+       # The presence of -? in the following pattern is only there to
+       # accommodate 0.29 && <= 2.05 RTS'
+       if ( /^\s*INIT\s+time\s*(\d+\.\d\d)s\s*\(\s*-?(\d+\.\d\d)s elapsed\)/ ) {
            $InitTime = $1; $InitElapsed = $2;
        } elsif ( /^\s*MUT\s+time\s*(\d+\.\d\d)s\s*\(\s*(\d+\.\d\d)s elapsed\)/ ) {
            $MutTime = $1; $MutElapsed = $2;
@@ -2222,8 +2289,10 @@ sub process_ghc_timings {
        }
     }
     close(STATS) || die "Failed when closing $StatsFile\n";
-    if ( defined($ResidencySamples) && $ResidencySamples > 0 ) {
-       $AvgResidency = int ($tot_live / $ResidencySamples) ;
+    if ( $tot_samples > 0 ) {
+       $ResidencySamples = $tot_samples;
+       $MaxResidency = $max_live;
+       $AvgResidency = int ($tot_live / $tot_samples) ;
     }
 
     # warn about what we didn't find
@@ -2308,7 +2377,7 @@ nonsensical).
 sub grab_arg_arg {
     local(*Args, $option, $rest_of_arg) = @_;
     
-    if ($rest_of_arg) {
+    if ($rest_of_arg ne '') {
        return($rest_of_arg);
     } elsif ($#Args >= 0) {
        local($temp) = $Args[0]; shift(@Args); 
@@ -2355,28 +2424,68 @@ sub add_Hsc_flags {
 }
 \end{code}
 
+\begin{code}
+sub add_syslib {
+    local($syslib) = @_;
+    
+    unshift(@SysImport_dir,
+           ${INSTALLING} ? "$InstLibDir/imports/$syslib"
+                         : "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/$syslib");
+
+    push(@SysLibrary_dir,
+        ${INSTALLING} ? ("$InstLibDir")
+                       : ("$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/$syslib",
+                         "$TopPwd/$CURRENT_DIR/$GHC_LIB_DIR/$syslib/cbits"));
+
+    push(@SysLibrary, "-lHS$syslib");
+    push(@SysLibrary, "-lHS${syslib}_cbits")
+          unless $syslib eq 'contrib' || $syslib eq 'exts';
+         #HACK! they have no cbits
+}
+\end{code}
+
 Source files may have {-# OPTIONS ... #-} pragmas at the top, containing
 command line options we want to append to collection of commands specified
 directly. @check_for_source_options@ looks at the top of a de-lit'ified Haskell
 file for any such pragmas:
 
 \begin{code}
-#
 sub check_for_source_options {
-    local($file, *FileArgs) = @_;
+    local($file,$ifile) = @_;
+    local($comment_start,$comment_end);
+
+    if ($ifile =~ /\.hc$/ || 
+        $ifile =~ /_hc$/  || 
+       $ifile =~ /\.s$/  || 
+       $ifile =~ /_s$/ ) {  # `Real' C intermediate
+       $comment_start = "/\\*";
+       $comment_end   = "\\*/";
+    } else { # Assume it is a file containing Haskell source
+       $comment_start = "{-#";
+       $comment_end   = "#-}";
+    }
 
-    open(FILE,$file) || return(1);
+    open(FILE,$file) || return(1); # No big loss
     
     while (<FILE>) {
-       if ( /^{-# OPTIONS (.*)#-}/ ) {
+       if ( /^${comment_start} OPTIONS (.*)${comment_end}$/ ) {
            # add the options found at the back of the command line.
-          push(@FileArgs, split(/\s+/, $1));
+          local(@entries) = split(/\s+/,$1);
+          print STDERR "Found OPTIONS " . join(' ',@entries) . " in $file\n" if $Verbose;
+          push(@File_options, @entries);
        }
         elsif ( /^$/ ) { # ignore empty lines
            ;
         }
-        else {
-           break;
+        elsif ( /^#line.+$/ ) { # ignore comment lines (unused..ToDo: rm )
+           ;
+        }
+        elsif ( /^{-# LINE.+$/ ) { # ignore line pragmas
+           ;
+        }
+        else { # stop looking, something non-empty / not
+              # ${comment_start} OPTIONS .. ${comment_end} encountered.
+           close(FILE);return(0);
         }
     }
     close(FILE);
@@ -2385,11 +2494,12 @@ sub check_for_source_options {
 \end{code}
 
 
-split up argv into three arrays:
+We split the initial argv up into three arrays:
 
   - @Cmd_opts 
   - @Link_file
   - @Input_file
+
 the reason for doing so is to be able to deal
 with {-# OPTIONS #-} pragma in source files properly.
 
@@ -2399,12 +2509,12 @@ sub splitCmdLine {
 
 arg: while($_ = $args[0]) {
     shift(@args);
-    # sigh, we have to deal with the -option arg specially.
-    /^-(tmpdir|odir|o|isuf|osuf|hisuf|odump|syslib)$/ && 
+    # sigh, we have to deal with these -option arg specially here.
+    /^-(tmpdir|odir|ohi|o|isuf|osuf|hisuf|hisuf-prelude|odump|syslib)$/ && 
        do { push(@Cmd_opts, $_); push(@Cmd_opts,$args[0]); shift(@args); next arg; };
-    /^-./  && do { push(@Cmd_opts, $_); next arg; };
+    /^--?./  && do { push(@Cmd_opts, $_); next arg; };
 
-    if (/\.[oa]$/) {
+    if (/\.([^_]+_)?[oa]$/) {
        push(@Link_file, $_);
     } else {
        push(@Input_file, $_);
@@ -2415,11 +2525,41 @@ arg: while($_ = $args[0]) {
        print STDERR "$Pgm: input file doesn't exist: $_\n";
        $Status++;
     }
-}
+  }
 }    
 
 \end{code}
 
+When saving an intermediate file (.hc or .s) away, we 
+have to prefix any OPTIONS found in the original source file.
+
+\begin{code}
+sub saveIntermediate { 
+  local ($final,$suffix,$tmp)= @_ ;
+  local ($to_do);
+
+  # $final  -- root of where to park ${final}.${suffix}
+  # $tmp    -- temporary file where hsc put the intermediate file.
+
+  # Delete the old file
+  $to_do = "$Rm ${final}.${suffix}"; &run_something($to_do, "Removing old .${suffix} file");
+
+  if ( $#File_options >= 0 ) { # OPTIONS found in Haskell source unit
+    # Add OPTION comment to the top of the generated .${suffix} file
+    open(TEMP, "> ${final}.${suffix}") || &tidy_up_and_die(1,"Can't open ${final}.${suffix}\n");
+    print TEMP "/* OPTIONS " . join(' ',@File_options) . " */\n";
+    close(TEMP);
+    print STDERR "Prepending OPTIONS: " . join(' ',@File_options) . " to ${final}.${suffix}\n" if $Verbose;
+  }
+  $to_do = "$Cat $tmp  >> ${final}.${suffix}";
+  &run_something($to_do, "Saving copy of .${suffix} file");
+
+}
+
+\end{code}
+
+
+Command-line processor
 
 \begin{code}
 sub processArgs {
@@ -2434,13 +2574,13 @@ arg: while($_ = $Args[0]) {
     if (/^-\?$/ || /^--?help$/) { print $LongUsage; exit $Status; }
 
     #-----------version ----------------------------------------------------
-    /^--version$/   && do { print STDERR "$(PROJECTNAME), version $(PROJECTVERSION) $(PROJECTPATCHLEVEL)\n"; exit $Status; };
+    /^--version$/   && do { print STDERR "${PROJECTNAME}, version ${PROJECTVERSION}, patchlevel ${PROJECTPATCHLEVEL}\n"; exit $Status; };
 
     #---------- verbosity and such -----------------------------------------
     /^-v$/         && do { $Verbose = '-v'; $Time = 'time'; next arg; };
 
     #---------- what phases are to be run ----------------------------------
-    /^-recomp/     && do { $Do_recomp_chkr = 1; next arg; };
+    /^-(no-)?recomp/       && do { $Do_recomp_chkr = ($1 eq '') ? 1 : 0; next arg; };
 
     /^-cpp$/       && do { $Cpp_flag_set = 1; next arg; };
     # change the global default:
@@ -2461,24 +2601,25 @@ arg: while($_ = $Args[0]) {
     /^-nohi$/      && do { $ProduceHi = '-nohifile='; next arg; };
     # don't generate an interface (even if generating C)
 
-    /^-hi-diffs$/             && do { $HiDiff_flag = 'normal'; next arg; };
-    /^-hi-diffs-with-usages$/ && do { $HiDiff_flag = 'usages'; next arg; };
-    /^-no-hi-diffs$/          && do { $HiDiff_flag = '';       next arg; };
+    /^-hi-diffs$/             && do { $HiDiff_flag  = 'normal'; next arg; };
+    /^-hi-diffs-with-usages$/ && do { $HiDiff_flag  = 'usages'; next arg; };
+    /^-no-hi-diffs$/          && do { $HiDiff_flag  = '';       next arg; };
+    /^-keep-hi-diffs$/       && do { $Keep_HiDiffs = 1; next arg; };
+
     # show/disable diffs if the interface file changes
 
     /^-E$/         && do { push(@CcBoth_flags, '-E');
                            $Only_preprocess_C = 1;
                            $Do_as = 0; $Do_lnkr = 0; next arg; };
     # stop after preprocessing C
-    /^-M$/         && do { $Only_generate_deps = 1;
-                           $Do_as = 0; $Do_lnkr = 0; next arg; };
-    # only generate 
+    /^-M$/         && do { $Only_generate_deps = 1; $Do_as = 0; $Do_lnkr = 0; next arg; };
+    # only generate dependency information.
     /^-S$/         && do { $Do_as = 0; $Do_lnkr = 0; next arg; };
     # stop after generating assembler
        
     /^-c$/         && do { $Do_lnkr = 0; next arg; };
     # stop after generating .o files
-       
+
     /^-link-chk$/    && do { $LinkChk = 1; next arg; };
     /^-no-link-chk$/ && do { $LinkChk = 0; next arg; };
     # don't do consistency-checking after a link
@@ -2496,7 +2637,11 @@ arg: while($_ = $Args[0]) {
     # if <file> has a directory component, that dir must already exist
 
     /^-odir$/      && do { $Specific_output_dir = &grab_arg_arg(*Args,'-odir', '');
-                           if (! -d $Specific_output_dir) {
+                           #
+                           # Hack, of the worst sort: don't do validation of
+                           # odir argument if you're using -M (dependency generation).
+                           #
+                           if ( ! $Only_generate_deps && ! -d $Specific_output_dir) {
                                print STDERR "$Pgm: -odir: no such directory: $Specific_output_dir\n";
                                $Status++;
                            }
@@ -2540,12 +2685,20 @@ arg: while($_ = $Args[0]) {
                            }
                            next arg; };
 
+    # The suffix to use when looking for interface files
     /^-hisuf$/     && do { $HiSuffix = &grab_arg_arg(*Args,'-hisuf', '');
                            if ($HiSuffix =~ /\./ ) {
                                print STDERR "$Pgm: -hisuf suffix shouldn't contain a .\n";
                                $Status++;
                            }
                            next arg; };
+    # ToDo: remove, not a `normal' user thing to do (should be automatic)
+    /^-hisuf-prelude$/     && do { $HiSuffix_prelude = &grab_arg_arg(*Args,'-hisuf-prelude', '');
+                           if ($HiSuffix =~ /\./ ) {
+                               print STDERR "$Pgm: -hisuf-prelude suffix shouldn't contain a .\n";
+                               $Status++;
+                           }
+                           next arg; };
     /^-odump$/     && do { $Specific_dump_file = &grab_arg_arg(*Args,'-odump', '');
                            if ($Specific_dump_file =~ /(.*)\/[^\/]*$/) {
                                local($dir_part) = $1;
@@ -2582,8 +2735,8 @@ arg: while($_ = $Args[0]) {
                        next arg; };
 
     /^-unprof-scc-auto/ && do {
-               # generate auto SCCs on top level bindings when not profiling
-               # used to measure optimisation effects of presence of sccs
+               # generate auto SCCs on top level bindings when not profiling.
+               # Used to measure optimisation effects of presence of sccs.
                $UNPROFscc_auto = ( /-all/ )
                            ? '-fauto-sccs-on-all-toplevs'
                            : '-fauto-sccs-on-exported-toplevs';
@@ -2592,60 +2745,18 @@ arg: while($_ = $Args[0]) {
     #--------- ticky/concurrent/parallel -----------------------------------
     # we sort out the details a bit later on
 
-    /^-concurrent$/ && do { $CONCURing = 'c'; next arg; }; # concurrent Haskell
+    /^-concurrent$/ && do { $CONCURing = 'c'; &add_syslib('conc'); next arg; }; 
+                         # concurrent Haskell; implies -syslib conc
     /^-gransim$/    && do { $GRANing   = 'g'; next arg; }; # GranSim
     /^-ticky$/     && do { $TICKYing  = 't'; next arg; }; # ticky-ticky
-    /^-parallel$/   && do { $PARing    = 'p'; next arg; } ; # parallel Haskell
+    /^-parallel$/   && do { $PARing    = 'p'; next arg; }; # parallel Haskell
 
     #-------------- "user ways" --------------------------------------------
 
-    (/^-user-setup-([a-oA-Z])$/
-    || /^$(GHC_BUILD_FLAG_a)$/
-    || /^$(GHC_BUILD_FLAG_b)$/
-    || /^$(GHC_BUILD_FLAG_c)$/
-    || /^$(GHC_BUILD_FLAG_d)$/
-    || /^$(GHC_BUILD_FLAG_e)$/
-    || /^$(GHC_BUILD_FLAG_f)$/
-    || /^$(GHC_BUILD_FLAG_g)$/
-    || /^$(GHC_BUILD_FLAG_h)$/
-    || /^$(GHC_BUILD_FLAG_i)$/
-    || /^$(GHC_BUILD_FLAG_j)$/
-    || /^$(GHC_BUILD_FLAG_k)$/
-    || /^$(GHC_BUILD_FLAG_l)$/
-    || /^$(GHC_BUILD_FLAG_m)$/
-    || /^$(GHC_BUILD_FLAG_n)$/
-    || /^$(GHC_BUILD_FLAG_o)$/
-    || /^$(GHC_BUILD_FLAG_A)$/
-    || /^$(GHC_BUILD_FLAG_B)$/
-
-    || /^$(GHC_BUILD_FLAG_2s)$/ # GC ones...
-    || /^$(GHC_BUILD_FLAG_1s)$/
-    || /^$(GHC_BUILD_FLAG_du)$/
-    ) && do {
+    (/^-user-setup-([a-oA-Z])$/ ) && 
+           do {
                /^-user-setup-([a-oA-Z])$/  && do { $BuildTag = "_$1"; };
 
-               /^$(GHC_BUILD_FLAG_a)$/  && do { $BuildTag = '_a';  };
-               /^$(GHC_BUILD_FLAG_b)$/  && do { $BuildTag = '_b';  };
-               /^$(GHC_BUILD_FLAG_c)$/  && do { $BuildTag = '_c';  };
-               /^$(GHC_BUILD_FLAG_d)$/  && do { $BuildTag = '_d';  };
-               /^$(GHC_BUILD_FLAG_e)$/  && do { $BuildTag = '_e';  };
-               /^$(GHC_BUILD_FLAG_f)$/  && do { $BuildTag = '_f';  };
-               /^$(GHC_BUILD_FLAG_g)$/  && do { $BuildTag = '_g';  };
-               /^$(GHC_BUILD_FLAG_h)$/  && do { $BuildTag = '_h';  };
-               /^$(GHC_BUILD_FLAG_i)$/  && do { $BuildTag = '_i';  };
-               /^$(GHC_BUILD_FLAG_j)$/  && do { $BuildTag = '_j';  };
-               /^$(GHC_BUILD_FLAG_k)$/  && do { $BuildTag = '_k';  };
-               /^$(GHC_BUILD_FLAG_l)$/  && do { $BuildTag = '_l';  };
-               /^$(GHC_BUILD_FLAG_m)$/  && do { $BuildTag = '_m';  };
-               /^$(GHC_BUILD_FLAG_n)$/  && do { $BuildTag = '_n';  };
-               /^$(GHC_BUILD_FLAG_o)$/  && do { $BuildTag = '_o';  };
-               /^$(GHC_BUILD_FLAG_A)$/  && do { $BuildTag = '_A';  };
-               /^$(GHC_BUILD_FLAG_B)$/  && do { $BuildTag = '_B';  };
-
-               /^$(GHC_BUILD_FLAG_2s)$/ && do { $BuildTag = '_2s'; };
-               /^$(GHC_BUILD_FLAG_1s)$/ && do { $BuildTag = '_1s'; };
-               /^$(GHC_BUILD_FLAG_du)$/ && do { $BuildTag = '_du'; };
-
                local($stuff) = $UserSetupOpts{$BuildTag};
                local(@opts)  = split(/\s+/, $stuff);
                
@@ -2677,24 +2788,21 @@ arg: while($_ = $Args[0]) {
                            print STDERR "$Pgm: no such system library (-syslib): $syslib\n",
                              $Status++ unless $syslib =~ /^(hbc|ghc|posix|contrib)$/;
 
-                           unshift(@SysImport_dir,
-                               $(INSTALLING)
-                               ? "$InstSysLibDir/$syslib/imports"
-                               : "$TopPwd/hslibs/$syslib/src");
-
-                           if ( $(INSTALLING) ) {
-                               push(@SysLibrary_dir,
-                                       ("$InstSysLibDir/$TargetPlatform"));
-                           } else {
-                               push(@SysLibrary_dir,
-                                       ("$TopPwd/hslibs/$syslib"
-                                       ,"$TopPwd/hslibs/$syslib/cbits"));
+                           #
+                           # The posix library is a `special' in that it relies on
+                           # the ghc system library (packed strings). Wielding our
+                           # sledgehammer, the problem is solved by silently including
+                           # the ghc system library as well.
+                           # (ToDo: `nub' -syslib list)
+                           #
+                           &add_syslib($syslib);
+                           if ( $syslib eq 'posix' ) {
+                               &add_syslib('ghc');
+                           } elsif ( $syslib eq 'ghc' && 
+                                     $TargetName =~ /-solaris2$/ ) {
+                               # needed for Berkeley socket/nwork stuff.
+                               push(@SysLibrary, '-lnsl');
                            }
-
-                           push(@SysLibrary, "-lHS$syslib");
-                           push(@SysLibrary, "-lHS${syslib}_cbits")
-                             unless $syslib eq 'contrib'; #HACK! it has no cbits
-
                            next arg; };
 
     #=======================================================================
@@ -2718,6 +2826,7 @@ arg: while($_ = $Args[0]) {
     /^-optP(.*)$/   && do { push(@HsCpp_flags,      $1); next arg; };
     /^-optCrts(.*)$/&& do { push(@HsC_rts_flags,    $1); next arg; };
     /^-optC(.*)$/   && do { push(@HsC_flags,        $1); next arg; };
+    /^-optcpp(.*)$/ && do { push(@Cpp_define,       $1); $Only_preprocess_hc = ($1 eq "-E"); next arg; };
     /^-optc(.*)$/   && do { push(@CcBoth_flags,     $1); next arg; };
     /^-opta(.*)$/   && do { push(@As_flags,         $1); next arg; };
     /^-optl(.*)$/   && do { push(@Ld_flags,         $1); next arg; };
@@ -2745,11 +2854,24 @@ arg: while($_ = $Args[0]) {
     /^-fignore-interface-pragmas$/ && do { push(@HsC_flags, $_); next arg; };
 
     /^-fno-implicit-prelude$/      && do { $NoImplicitPrelude= 1; push(@HsC_flags, $_); next arg; };
-    /^-user-prelude-force/     && do { # ignore if not -user-prelude
-                                       next arg; };
+     # don't do stack checking using page fault `trick'.
+     # (esoteric).
+    /^-fstack-check$/             && do { $StkChkByPageFaultOK = 0; next arg; };
+     #
+     # have the compiler proper generate concurrent code,
+     # really only used when you want to configure your own
+     # special user compilation way. (Use -concurrent when
+     # compiling `Concurrent Haskell' programs).
+     #
+     # (ditto for -fgransim, fscc-profiling and -fticky-ticky)
+     #
+    /^-fconcurrent$/      && do { push(@HsC_flags,$_); next arg; };
+    /^-fscc-profiling$/   && do { push(@HsC_flags,$_); next arg; };
+    /^-fticky-ticky$/     && do { push(@HsC_flags,$_); next arg; };
+    /^-fgransim$/        && do { push(@HsC_flags,$_); next arg; };
 
     /^-split-objs/     && do {
-                       if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|sparc)-/ ) {
+                       if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|rs6000|sparc)-/ ) {
                            $SplitObjFiles = 0;
                            print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n";
                        } else {
@@ -2769,6 +2891,9 @@ arg: while($_ = $Args[0]) {
                        push(@HsP_flags, '-N');
 
 #                      push(@HsC_flags, '-fshow-import-specs');
+               
+                       # -fglasgow-exts implies -syslib exts
+                       &add_syslib('exts');
 
                        next arg; };
 
@@ -2807,10 +2932,16 @@ arg: while($_ = $Args[0]) {
                    && do { $Oopt_FoldrBuildInline .= ' -fdo-not-fold-back-append '; 
                            next arg; };
 
+    # --------------- Renamer -------------
+
+
+    /^-fno-prune-tydecls$/     && do { push(@HsC_flags, $_); next arg; };
+    /^-fno-prune-instdecls$/     && do { push(@HsC_flags, $_); next arg; };
+
     # ---------------
 
     /^-fasm-(.*)$/  && do { $HscOut = '-S='; next arg; }; # force using nativeGen
-    /^-fvia-C$/            && do { $HscOut = '-C='; next arg; }; # force using C compiler
+    /^-fvia-[cC]$/         && do { $HscOut = '-C='; next arg; }; # force using C compiler
 
     # ---------------
 
@@ -2821,6 +2952,9 @@ arg: while($_ = $Args[0]) {
     /^(-fmax-simplifier-iterations)(.*)$/
                    && do { $Oopt_MaxSimplifierIterations = $1 . &grab_arg_arg(*Args,$1, $2);
                            next arg; };
+    /^(-fshow-simplifier-progress)/
+                   && do { $Oopt_ShowSimplifierProgress = $1;
+                           next arg; };
 
     /^-fno-pedantic-bottoms$/
                    && do { $Oopt_PedanticBottoms = ''; next arg; };
@@ -2843,18 +2977,33 @@ arg: while($_ = $Args[0]) {
                            }
                            next arg; };
 
-    # ---------------
+    # --------------- Warnings etc. ------
+
+    /^-fshow-import-specs/
+                   && do { push(@HsC_flags, $_); next arg; };
+
+    /^-fsignatures-required/      
+                   && do { push(@HsC_flags, $_); next arg; };
+
+    /^-fwarn-(.*)$/      && do { push(@HsC_flags, $_); next arg; };
 
     /^-fno-(.*)$/   && do { push(@HsC_antiflags, "-f$1");
                            &squashHscFlag("-f$1");
                            next arg; };
 
-    /^-f(show-import-specs)/
-                   && do { push(@HsC_flags, $_); next arg; };
+    /^-W$/         && do { push(@HsC_flags, @MinusWOpts); next arg; };
+    /^-Wall$/      && do { push(@HsC_flags, @MinusWallOpts); next arg; };
+    /^(-Wnot|w)$/   && do { foreach (@Hsc_flags) {
+                               /^-fwarn-(.*)$/ && do { $_=''; };
+                           };
+                           push(@HsC_antiflags, @StandardWarnings);
+                           next arg; };
 
     # --------------- platform specific flags (for gcc mostly) ----------------
 
-    /^-mlong-calls$/ && do { # for GCC for HP-PA boxes
+    /^-mlong-calls$/ && do { # for GCC for HP-PA boxes,
+                             # for 2.6.x..?, does not apply for 2.7.2
+                            # any longer.
                            unshift(@CcBoth_flags, ( $_ ));
                            next arg; };
 
@@ -2872,10 +3021,14 @@ arg: while($_ = $Args[0]) {
     # -d(no-)core-lint is done this way so it is turn-off-able.
     /^-dcore-lint/       && do { $CoreLint = '-dcore-lint'; next arg; };
     /^-dno-core-lint/    && do { $CoreLint = '';           next arg; };
+    # Ditto for STG lint
+    /^-dstg-lint/       && do { $StgLint = '-dstg-lint'; next arg; };
+    /^-dno-stg-lint/    && do { $StgLint = '';           next arg; };
 
     /^-d(dump|ppr)-/         && do { push(@HsC_flags, $_); next arg; };
     /^-dverbose-(simpl|stg)/ && do { push(@HsC_flags, $_); next arg; };
     /^-dshow-passes/        && do { push(@HsC_flags, $_); next arg; };
+    /^-dshow-rn-stats/      && do { push(@HsC_flags, $_); next arg; };
     /^-dshow-rn-trace/      && do { push(@HsC_flags, $_); next arg; };
     /^-dsource-stats/        && do { push(@HsC_flags, $_); next arg; };
     /^-dsimplifier-stats/    && do { push(@HsC_flags, $_); next arg; };
@@ -2908,7 +3061,8 @@ arg: while($_ = $Args[0]) {
        }
        next arg; };
 
-    /^-(K|Rmax-(stk|stack)size)(.*)/ && do {
+    /^(-K|Rmax-(stk|stack)size)(.*)/ && do {
+        local($flag) = $1;
        local($stk_size) = &grab_arg_arg(*Args,'-Rmax-stksize', $3);
        if ($stk_size =~ /(\d+)[Kk]$/) {
            $stk_size = $1 * 1000;
@@ -2918,14 +3072,14 @@ arg: while($_ = $Args[0]) {
            $stk_size = $1 * 1000 * 1000 * 1000;
        }
        if ($stk_size <= 0) {
-           print STDERR "$Pgm: resetting stack-size to zero!!!\n";
+           print STDERR "$Pgm: resetting stack-size to zero!!! $stk_size\n";
            $Specific_stk_size = 0;
 
        # if several stack sizes given, take the largest...
        } elsif ($stk_size >= $Specific_stk_size) {
            $Specific_stk_size = $stk_size;
        } else {
-           print STDERR "$Pgm: ignoring stack-size-setting option (-Rmax-stksize $stk_size)...not the largest seen\n";
+           print STDERR "$Pgm: ignoring stack-size-setting option ($flag $stk_size)...not the largest seen\n";
        }
        next arg; };
 
@@ -2961,7 +3115,6 @@ arg: while($_ = $Args[0]) {
     /^-O2-for-C$/ && do { $MinusO2ForC = 1; next arg; };
 
     /^-O[1-2]?$/ && do {
-#              print STDERR "$Pgm: NOTE: this version of GHC doesn't support -O or -O2\n";
                local($opt_lev) = ( /^-O2$/ ) ? 2 : 1; # max 'em
                $OptLevel = ( $opt_lev > $OptLevel ) ? $opt_lev : $OptLevel;