+
+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) = @_;
+
+ open(FILE,$file) || return(1); # No big loss
+
+ while (<FILE>) {
+ if ( /^{-# OPTIONS (.*)#-}/ ) {
+ # add the options found at the back of the command line.
+ local(@entries) = split(/\s+/,$1);
+ push(@File_options, @entries);
+ }
+ elsif ( /^$/ ) { # ignore empty lines
+ ;
+ }
+ else { # stop looking, something non-empty / not
+ # {-# OPTIONS .. #-} encountered.
+ break;
+ }
+ }
+ close(FILE);
+ return(0);
+}
+\end{code}
+
+
+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.
+
+\begin{code}
+sub splitCmdLine {
+ local(@args) = @_;
+
+arg: while($_ = $args[0]) {
+ shift(@args);
+ # sigh, we have to deal with these -option arg specially here.
+ /^-(tmpdir|odir|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; };
+
+ if (/\.[oa]$/) {
+ push(@Link_file, $_);
+ } else {
+ push(@Input_file, $_);
+ }
+
+ # input files must exist:
+ if (! -f $_) {
+ print STDERR "$Pgm: input file doesn't exist: $_\n";
+ $Status++;
+ }
+ }
+}
+
+\end{code}
+
+Command-line processor
+
+\begin{code}
+sub processArgs {
+ local(@Args) = @_;
+
+# can't use getopt(s); what we want is too complicated
+
+arg: while($_ = $Args[0]) {
+ shift(@Args);
+
+ #---------- help -------------------------------------------------------
+ if (/^-\?$/ || /^--?help$/) { print $LongUsage; exit $Status; }
+
+ #-----------version ----------------------------------------------------
+ /^--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; };
+
+ /^-cpp$/ && do { $Cpp_flag_set = 1; next arg; };
+ # change the global default:
+ # we won't run cat; we'll run the real thing
+
+ /^-C$/ && do { $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0; $HscOut = '-C=';
+ next arg; };
+ # stop after generating C
+
+ /^-noC$/ && do { $HscOut = '-N='; $ProduceHi = '-nohifile=';
+ $Do_cc = 0; $Do_as = 0; $Do_lnkr = 0;
+ next arg; };
+ # leave out actual C generation (debugging) [also turns off interface gen]
+
+ /^-hi$/ && do { $HiOnStdout = 1; $ProduceHi = '-hifile='; next arg; };
+ # _do_ generate an interface; usually used as: -noC -hi
+
+ /^-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; };
+ # 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 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
+
+ /^-tmpdir$/ && do { $Tmp_prefix = &grab_arg_arg(*Args,'-tmpdir', '');
+ $Tmp_prefix = "$Tmp_prefix/ghc$$";
+ $ENV{'TMPDIR'} = $Tmp_prefix; # for those who use it...
+ next arg; };
+ # use an alternate directory for temp files
+
+ #---------- redirect output --------------------------------------------
+
+ # -o <file>; applies to the last phase, whatever it is
+ # "-o -" sends it to stdout
+ # if <file> has a directory component, that dir must already exist
+
+ /^-odir$/ && do { $Specific_output_dir = &grab_arg_arg(*Args,'-odir', '');
+ #
+ # 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++;
+ }
+ next arg; };
+
+ /^-o$/ && do { $Specific_output_file = &grab_arg_arg(*Args,'-o', '');
+ if ($Specific_output_file ne '-'
+ && $Specific_output_file =~ /(.*)\/[^\/]*$/) {
+ local($dir_part) = $1;
+ if (! -d $dir_part) {
+ print STDERR "$Pgm: no such directory: $dir_part\n";
+ $Status++;
+ }
+ }
+ next arg; };
+
+ # NB: -isuf not documented yet (because it doesn't work yet)
+ /^-isuf$/ && do { $Isuffix = &grab_arg_arg(*Args,'-isuf', '');
+ if ($Isuffix =~ /\./ ) {
+ print STDERR "$Pgm: -isuf suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+
+ /^-osuf$/ && do { $Osuffix = &grab_arg_arg(*Args,'-osuf', '');
+ if ($Osuffix =~ /\./ ) {
+ print STDERR "$Pgm: -osuf suffix shouldn't contain a .\n";
+ $Status++;
+ }
+ next arg; };
+
+ # -ohi <file>; send the interface to <file>; "-ohi -" to send to stdout
+ /^-ohi$/ && do { $Specific_hi_file = &grab_arg_arg(*Args,'-ohi', '');
+ if ($Specific_hi_file ne '-'
+ && $Specific_hi_file =~ /(.*)\/[^\/]*$/) {
+ local($dir_part) = $1;
+ if (! -d $dir_part) {
+ print STDERR "$Pgm: no such directory: $dir_part\n";
+ $Status++;
+ }
+ }
+ 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;
+ if (! -d $dir_part) {
+ print STDERR "$Pgm: no such directory: $dir_part\n";
+ $Status++;
+ }
+ }
+ next arg; };
+
+ #-------------- scc & Profiling Stuff ----------------------------------
+
+ /^-prof$/ && do { $PROFing = 'p'; next arg; }; # profiling -- details later!
+
+ /^-auto/ && do {
+ # generate auto SCCs on top level bindings
+ # -auto-all = all top level bindings
+ # -auto = only top level exported bindings
+ $PROFauto = ( /-all/ )
+ ? '-fauto-sccs-on-all-toplevs'
+ : '-fauto-sccs-on-exported-toplevs';
+ next arg; };
+
+ /^-caf-all/ && do { # generate individual CAF SCC annotations
+ $PROFcaf = '-fauto-sccs-on-individual-cafs';
+ next arg; };
+
+ /^-ignore-scc$/ && do {
+ # forces ignore of scc annotations even if profiling
+ $PROFignore_scc = '-W';
+ next arg; };
+
+ /^-G(.*)$/ && do { push(@HsC_flags, "-G=$1"); # set group for cost centres
+ 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.
+ $UNPROFscc_auto = ( /-all/ )
+ ? '-fauto-sccs-on-all-toplevs'
+ : '-fauto-sccs-on-exported-toplevs';
+ next arg; };
+
+ #--------- ticky/concurrent/parallel -----------------------------------
+ # we sort out the details a bit later on
+
+ /^-concurrent$/ && do { $CONCURing = 'c'; next arg; }; # concurrent Haskell
+ /^-gransim$/ && do { $GRANing = 'g'; next arg; }; # GranSim
+ /^-ticky$/ && do { $TICKYing = 't'; next arg; }; # ticky-ticky
+ /^-parallel$/ && do { $PARing = 'p'; next arg; }; # parallel Haskell
+
+ #-------------- "user ways" --------------------------------------------
+
+ (/^-user-setup-([a-oA-Z])$/ ) &&
+ do {
+ /^-user-setup-([a-oA-Z])$/ && do { $BuildTag = "_$1"; };
+
+ local($stuff) = $UserSetupOpts{$BuildTag};
+ local(@opts) = split(/\s+/, $stuff);
+
+ # feed relevant ops into the arg-processing loop (if any)
+ unshift(@Args, @opts) if $#opts >= 0;
+
+ next arg; };
+
+ #---------- set search paths for libraries and things ------------------
+
+ # we do -i just like HBC (-i clears the list; -i<colon-separated-items>
+ # prepends the items to the list); -I is for including C .h files.
+
+ /^-i$/ && do { @Import_dir = (); # import path cleared!
+ @SysImport_dir = ();
+ print STDERR "WARNING: import paths cleared by `-i'\n";
+ next arg; };
+
+ /^-i(.*)/ && do { local(@new_items)
+ = split( /:/, &grab_arg_arg(*Args,'-i', $1));
+ unshift(@Import_dir, @new_items);
+ next arg; };
+
+ /^-I(.*)/ && do { push(@Include_dir, &grab_arg_arg(*Args,'-I', $1)); next arg; };
+ /^-L(.*)/ && do { push(@UserLibrary_dir, &grab_arg_arg(*Args,'-L', $1)); next arg; };
+ /^-l(.*)/ && do { push(@UserLibrary,'-l'.&grab_arg_arg(*Args,'-l', $1)); next arg; };
+
+ /^-syslib(.*)/ && do { local($syslib) = &grab_arg_arg(*Args,'-syslib',$1);
+ 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"));
+ } else {
+ push(@SysLibrary_dir,
+ ("$TopPwd/hslibs/$syslib"
+ ,"$TopPwd/hslibs/$syslib/cbits"));
+ }
+
+ push(@SysLibrary, "-lHS$syslib");
+ push(@SysLibrary, "-lHS${syslib}_cbits")
+ unless $syslib eq 'contrib'; #HACK! it has no cbits
+
+ next arg; };
+
+ #=======================================================================
+ # various flags that we can harmlessly send to one program or another
+ # (we will later "reclaim" some of the compiler ones now sent to gcc)
+ #=======================================================================
+
+ #---------- this driver itself (ghc) -----------------------------------
+ # these change what executable is run for each phase:
+ /^-pgmL(.*)$/ && do { $Unlit = $1; next arg; };
+ /^-pgmP(.*)$/ && do { $HsCpp = $1; next arg; };
+ /^-pgmC(.*)$/ && do { $HsC = $1; next arg; };
+ /^-pgmcO?(.*)$/ && do { $CcRegd = $1; next arg; }; # the O? for back compat
+ /^-pgma(.*)$/ && do { $As = $1; next arg; };
+ /^-pgml(.*)$/ && do { $Lnkr = $1; next arg; };
+ /^-pgmdep(.*)$/ && do { $MkDependHS = $1; next arg; };
+
+ #---------- the get-anything-through opts (all pgms) -------------------
+ # these allow arbitrary option-strings to go to any phase:
+ /^-optL(.*)$/ && do { push(@Unlit_flags, $1); next arg; };
+ /^-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); 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; };
+ /^-optdep(.*)$/ && do { push(@MkDependHS_flags, $1); next arg; };
+
+ #---------- Haskell C pre-processor (hscpp) ----------------------------
+ /^-D(.*)/ && do { push(@HsCpp_flags, "'-D".&grab_arg_arg(*Args,'-D',$1)."'"); next arg; };
+ /^-U(.*)/ && do { push(@HsCpp_flags, "'-U".&grab_arg_arg(*Args,'-U',$1)."'"); next arg; };
+
+ /^-genSPECS/ && do { $Cpp_flag_set = 1;
+ $genSPECS_flag = $_;
+ next arg; };
+
+ #---------- post-Haskell "assembler"------------------------------------
+ /^-ddump-raw-asm$/ && do { $Dump_raw_asm = 1; next arg; };
+ /^-ddump-asm-splitting-info$/ && do { $Dump_asm_splitting_info = 1; next arg; };
+
+ #---------- Haskell compiler (hsc) -------------------------------------
+
+ /^-keep-hc-files?-too$/ && do { $Keep_hc_file_too = 1; next arg; };
+ /^-keep-s-files?-too$/ && do { $Keep_s_file_too = 1; next arg; };
+
+ /^-fhaskell-1\.3$/ && do { next arg; }; # a no-op right now
+
+ /^-fignore-interface-pragmas$/ && do { push(@HsC_flags, $_); next arg; };
+
+ /^-fno-implicit-prelude$/ && do { $NoImplicitPrelude= 1; push(@HsC_flags, $_); 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; };
+
+ /^-user-prelude-force/ && do { # ignore if not -user-prelude
+ next arg; };
+
+ /^-split-objs/ && do {
+ if ( $TargetPlatform !~ /^(alpha|hppa1\.1|i386|m68k|mips|powerpc|sparc)-/ ) {
+ $SplitObjFiles = 0;
+ print STDERR "WARNING: don't know how to split objects on this platform: $TargetPlatform\n`-split-objs' option ignored\n";
+ } else {
+ $SplitObjFiles = 1;
+ $HscOut = '-C=';
+
+ push(@HsC_flags, "-fglobalise-toplev-names");
+ push(@CcBoth_flags, '-DUSE_SPLIT_MARKERS');
+
+ require('ghc-split.prl')
+ || &tidy_up_and_die(1,"$Pgm: panic: can't load ghc-split.prl!\n");
+ }
+ next arg; };
+
+ /^-fglasgow-exts$/
+ && do { push(@HsC_flags, $_);
+ push(@HsP_flags, '-N');
+
+# push(@HsC_flags, '-fshow-import-specs');
+
+ next arg; };
+
+ /^-fspeciali[sz]e-unboxed$/
+ && do { $Oopt_DoSpecialise = '-fspecialise';
+ $Oopt_SpecialiseUnboxed = '-fspecialise-unboxed';
+ next arg; };
+ /^-fspeciali[sz]e$/
+ && do { $Oopt_DoSpecialise = '-fspecialise'; next arg; };
+ /^-fno-speciali[sz]e$/
+ && do { $Oopt_DoSpecialise = ''; next arg; };
+
+
+# Now the foldr/build options, which are *on* by default (for -O).
+
+ /^-ffoldr-build$/
+ && do { $Oopt_FoldrBuild = 1;
+ $Oopt_FB_Support = '-fdo-arity-expand';
+ #print "Yes F/B\n";
+ next arg; };
+
+ /^-fno-foldr-build$/
+ && do { $Oopt_FoldrBuild = 0;
+ $Oopt_FB_Support = '';
+ next arg; };
+
+ /^-fno-foldr-build-rule$/
+ && do { $Oopt_FoldrBuild = 0;
+ next arg; };
+
+ /^-fno-enable-tech$/
+ && do { $Oopt_FB_Support = '';
+ next arg; };
+
+ /^-fno-snapback-to-append$/
+ && do { $Oopt_FoldrBuildInline .= ' -fdo-not-fold-back-append ';
+ next arg; };
+
+ # ---------------
+
+ /^-fasm-(.*)$/ && do { $HscOut = '-S='; next arg; }; # force using nativeGen
+ /^-fvia-C$/ && do { $HscOut = '-C='; next arg; }; # force using C compiler
+
+ # ---------------
+
+ /^(-funfolding-use-threshold)(.*)$/
+ && do { $Oopt_UnfoldingUseThreshold = $1 . &grab_arg_arg(*Args,$1, $2);
+ next arg; };
+
+ /^(-fmax-simplifier-iterations)(.*)$/
+ && do { $Oopt_MaxSimplifierIterations = $1 . &grab_arg_arg(*Args,$1, $2);
+ next arg; };
+
+ /^-fno-pedantic-bottoms$/
+ && do { $Oopt_PedanticBottoms = ''; next arg; };
+
+ /^-fdo-monad-eta-expansion$/
+ && do { $Oopt_MonadEtaExpansion = $_; next arg; };
+
+ /^-fno-let-from-(case|app|strict-let)$/ # experimental, really (WDP 95/10)
+ && do { push(@HsC_flags, $_); next arg; };
+
+ /^(-freturn-in-regs-threshold)(.*)$/
+ && do { local($what) = $1;
+ local($num) = &grab_arg_arg(*Args,$what, $2);
+ if ($num < 2 || $num > 8) {
+ die "Bad experimental flag: $_\n";
+ } else {
+ $HscOut = '-C='; # force using C compiler
+ push(@HsC_flags, "$what$num");
+ push(@CcRegd_flags, "-D__STG_REGS_AVAIL__=$num");
+ }
+ next arg; };
+
+ # --------------- Warnings etc. ------
+
+ /^-f(show-import-specs)/
+ && do { push(@HsC_flags, $_); next arg; };
+
+ # for now, just -fwarn-name-shadowing
+ /^-fwarn-(.*)$/ && do { push(@HsC_flags, $_); next arg; };
+ /^-fno-(.*)$/ && do { push(@HsC_antiflags, "-f$1");
+ &squashHscFlag("-f$1");
+ next arg; };
+
+ # --------------- platform specific flags (for gcc mostly) ----------------
+
+ /^-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; };
+
+ /^-m(v8|sparclite|cypress|supersparc|cpu=(cypress|supersparc))$/
+ && do { # for GCC for SPARCs
+ unshift(@CcBoth_flags, ( $_ ));
+ next arg; };
+
+ /^-monly-([432])-regs/ && do { # for iX86 boxes only; no effect otherwise
+ $StolenX86Regs = $1;
+ next arg; };
+
+ #*************** ... and lots of debugging ones (form: -d* )
+
+ # -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-trace/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dsource-stats/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dsimplifier-stats/ && do { push(@HsC_flags, $_); next arg; };
+ /^-dstg-stats/ && do { $Oopt_StgStats = $_; next arg; };
+
+ #*************** ... and now all these -R* ones for its runtime system...
+
+ /^-Rscale-sizes?(.*)/ && do {
+ $Scale_sizes_by = &grab_arg_arg(*Args,'-Rscale-sizes', $1);
+ next arg; };
+
+ /^(-H|-Rmax-heapsize)(.*)/ && do {
+ local($heap_size) = &grab_arg_arg(*Args,$1, $2);
+ if ($heap_size =~ /(\d+)[Kk]$/) {
+ $heap_size = $1 * 1000;
+ } elsif ($heap_size =~ /(\d+)[Mm]$/) {
+ $heap_size = $1 * 1000 * 1000;
+ } elsif ($heap_size =~ /(\d+)[Gg]$/) {
+ $heap_size = $1 * 1000 * 1000 * 1000;
+ }
+ if ($heap_size <= 0) {
+ print STDERR "$Pgm: resetting heap-size to zero!!! $heap_size\n";
+ $Specific_heap_size = 0;
+
+ # if several heap sizes given, take the largest...
+ } elsif ($heap_size >= $Specific_heap_size) {
+ $Specific_heap_size = $heap_size;
+ } else {
+ print STDERR "$Pgm: ignoring heap-size-setting option ($_)...not the largest seen\n";
+ }
+ next arg; };
+
+ /^-(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;
+ } elsif ($stk_size =~ /(\d+)[Mm]$/) {
+ $stk_size = $1 * 1000 * 1000;
+ } elsif ($stk_size =~ /(\d+)[Gg]$/) {
+ $stk_size = $1 * 1000 * 1000 * 1000;
+ }
+ if ($stk_size <= 0) {
+ 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 ($flag $stk_size)...not the largest seen\n";
+ }
+ next arg; };
+
+ /^-Rgc-stats$/ && do { $CollectingGCstats++;
+ # the two RTSs do this diff ways; we will try to compensate
+ next arg; };
+
+ /^-Rghc-timing/ && do { $CollectGhcTimings = 1; next arg; };
+
+ #---------- C high-level assembler (gcc) -------------------------------
+ /^-(Wall|ansi|pedantic)$/ && do { push(@CcBoth_flags, $_); next arg; };
+
+ # -dgcc-lint is a useful way of making GCC very fussy.
+ # From alan@spri.levels.unisa.edu.au (Alan Modra).
+ /^-dgcc-lint$/ && do { push(@CcBoth_flags, '-Wall -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs'); next arg; };
+ # An alternate set, from mark@sgcs.com (Mark W. Snitily)
+ # -Wall -Wstrict-prototypes -Wmissing-prototypes -Wcast-align -Wshadow
+
+ # inject "#include <wurble>" into the compiler's C output!
+
+ /^-#include(.*)/ && do {
+ local($to_include) = &grab_arg_arg(*Args,'-#include', $1);
+ push(@CcInjects, "#include $to_include\n");
+ next arg; };
+
+ #---------- Linker (gcc, really) ---------------------------------------
+
+ /^-static$/ && do { push(@Ld_flags, $_); next arg; };
+
+ #---------- mixed cc and linker magic ----------------------------------
+ # this optimisation stuff is finally sorted out later on...
+
+ /^-O2-for-C$/ && do { $MinusO2ForC = 1; next arg; };
+
+ /^-O[1-2]?$/ && do {
+ local($opt_lev) = ( /^-O2$/ ) ? 2 : 1; # max 'em
+ $OptLevel = ( $opt_lev > $OptLevel ) ? $opt_lev : $OptLevel;
+
+ $HscOut = '-C=' if $OptLevel == 2; # force use of C compiler
+ next arg; };
+
+ /^-Onot$/ && do { $OptLevel = 0; next arg; }; # # set it to <no opt>
+
+ /^-Ofile(.*)/ && do {
+ $OptLevel = 3;
+ local($ofile) = &grab_arg_arg(*Args,'-Ofile', $1);
+ @HsC_minusO3_flags = ();
+
+ open(OFILE, "< $ofile") || die "Can't open $ofile!\n";
+ while (<OFILE>) {
+ chop;
+ s/\#.*//; # death to comments
+ s/[ \t]+//g; # death to whitespace
+ next if /^$/; # ditto, blank lines
+ s/([()*{}])/\\$1/g; # protect shell metacharacters
+ if ( /^C:(.*)/ ) {
+ push(@CcBoth_flags, $1);
+ } else {
+ push(@HsC_minusO3_flags, $_);
+ }
+ }
+ close(OFILE);
+ next arg; };
+
+ /^-debug$/ && do { # all this does is mark a .hc/.o as "debugging"
+ # in the consistency info
+ $DEBUGging = 'd';
+ next arg; };
+
+ #---------- linking .a file --------------------------------------------
+
+ /^-Main(.*)/ && do {
+ # specifies main or mainPrimIO to be linked
+ $Ld_main = $1;
+ next arg; };
+
+ #---------- catch unrecognized flags -----------------------------------
+
+ /^-./ && do {
+ print STDERR "$Pgm: unrecognised option: $_\n";
+ $Status++;
+ next arg; };
+
+}
+
+} # end of processArgs
+
+\end{code}