<commit_before>{-# OPTIONS -fno-warn-incomplete-patterns -optc-DNON_POSIX_SOURCE #-}
-----------------------------------------------------------------------------
--
-- GHC Driver program
--
-- (c) The University of Glasgow 2005
--
-----------------------------------------------------------------------------

module Main (main) where

#include "HsVersions.h"

-- The official GHC API
import qualified GHC
import GHC		( Session, DynFlags(..), GhcMode(..), HscTarget(..),
			  LoadHowMuch(..), dopt, DynFlag(..) )
import CmdLineParser

-- Implementations of the various modes (--show-iface, mkdependHS. etc.)
import LoadIface	( showIface )
import HscMain          ( newHscEnv )
import DriverPipeline	( oneShot, compileFile )
import DriverMkDepend	( doMkDependHS )
#ifdef GHCI
import InteractiveUI	( ghciWelcomeMsg, interactiveUI )
#endif

-- Various other random stuff that we need
import Config		( cProjectVersion, cBooterVersion, cProjectName )
import Packages		( dumpPackages )
import DriverPhases	( Phase(..), isSourceFilename, anyHsc,
			  startPhase, isHaskellSrcFilename )
import StaticFlags
import DynFlags         ( defaultDynFlags )
import BasicTypes	( failed )
import ErrUtils		( putMsg )
import FastString	( getFastStringTable, isZEncoded, hasZEncoding )
import Outputable
import Util
import Panic

-- Standard Haskell libraries
import Control.Exception ( throwDyn )
import System.IO
import System.Directory	( doesDirectoryExist )
import System.Environment
import System.Exit
import Control.Monad
import Data.List
import Data.Maybe

-----------------------------------------------------------------------------
-- ToDo:

-- time commands when run with -v
-- user ways
-- Win32 support: proper signal handling
-- reading the package configuration file is too slow
-- -K<size>

-----------------------------------------------------------------------------
-- GHC's command-line interface

main =
  GHC.defaultErrorHandler defaultDynFlags $ do
  
  -- 1. extract the -B flag from the args
  argv0 <- getArgs

  let
        (minusB_args, argv1) = partition (prefixMatch "-B") argv0
        mbMinusB | null minusB_args = Nothing
                 | otherwise = Just (drop 2 (last minusB_args))

  argv2 <- parseStaticFlags argv1

  -- 2. Parse the "mode" flags (--make, --interactive etc.)
  (cli_mode, argv3) <- parseModeFlags argv2

  let mode = case cli_mode of
		DoInteractive	-> Interactive
		DoEval _	-> Interactive
		DoMake		-> BatchCompile
		DoMkDependHS	-> MkDepend
		_		-> OneShot

  -- start our GHC session
  session <- GHC.newSession mode mbMinusB

  dflags0 <- GHC.getSessionDynFlags session

  -- set the default HscTarget.  The HscTarget can be further
  -- adjusted on a module by module basis, using only the -fvia-C and
  -- -fasm flags.  If the default HscTarget is not HscC or HscAsm,
  -- -fvia-C and -fasm have no effect.
  let lang = case cli_mode of 
		 DoInteractive  -> HscInterpreted
		 DoEval _	-> HscInterpreted
		 _other		-> hscTarget dflags0

  let dflags1 = dflags0{ ghcMode = mode,
                  	 hscTarget  = lang,
			 -- leave out hscOutName for now
	                 hscOutName = panic "Main.main:hscOutName not set",
		  	 verbosity = case cli_mode of
				 	 DoEval _ -> 0
				 	 _other   -> 1
			}

	-- The rest of the arguments are "dynamic"
	-- Leftover ones are presumably files
  (dflags, fileish_args) <- GHC.parseDynamicFlags dflags1 argv3

	-- make sure we clean up after ourselves
  GHC.defaultCleanupHandler dflags $ do

	-- Display banner
  showBanner cli_mode dflags

  -- we've finished manipulating the DynFlags, update the session
  GHC.setSessionDynFlags session dflags
  dflags <- GHC.getSessionDynFlags session

  let
     -- To simplify the handling of filepaths, we normalise all filepaths right 
     -- away - e.g., for win32 platforms, backslashes are converted
     -- into forward slashes.
    normal_fileish_paths = map normalisePath fileish_args
    (srcs, objs)         = partition_args normal_fileish_paths [] []

  -- Note: have v_Ld_inputs maintain the order in which 'objs' occurred on 
  --       the command-line.
  mapM_ (consIORef v_Ld_inputs) (reverse objs)

	---------------- Display configuration -----------
  when (verbosity dflags >= 4) $
	dumpPackages dflags

  when (verbosity dflags >= 3) $ do
	hPutStrLn stderr ("Hsc static flags: " ++ unwords staticFlags)

	---------------- Final sanity checking -----------
  checkOptions cli_mode dflags srcs objs

	---------------- Do the business -----------
  case cli_mode of
	ShowUsage       -> showGhcUsage dflags cli_mode
	PrintLibdir     -> putStrLn (topDir dflags)
	ShowVersion     -> showVersion
        ShowNumVersion  -> putStrLn cProjectVersion
        ShowInterface f -> doShowIface dflags f
	DoMake 	        -> doMake session srcs
	DoMkDependHS    -> doMkDependHS session (map fst srcs)
	StopBefore p    -> oneShot dflags p srcs
	DoInteractive   -> interactiveUI session srcs Nothing
	DoEval expr     -> interactiveUI session srcs (Just expr)

  dumpFinalStats dflags
  exitWith ExitSuccess

#ifndef GHCI
interactiveUI _ _ _ = 
  throwDyn (CmdLineError "not built for interactive use")
#endif

-- -----------------------------------------------------------------------------
-- Splitting arguments into source files and object files.  This is where we
-- interpret the -x <suffix> option, and attach a (Maybe Phase) to each source
-- file indicating the phase specified by the -x option in force, if any.

partition_args [] srcs objs = (reverse srcs, reverse objs)
partition_args ("-x":suff:args) srcs objs
  | "none" <- suff	= partition_args args srcs objs
  | StopLn <- phase	= partition_args args srcs (slurp ++ objs)
  | otherwise		= partition_args rest (these_srcs ++ srcs) objs
	where phase = startPhase suff
	      (slurp,rest) = break (== "-x") args 
	      these_srcs = zip slurp (repeat (Just phase))
partition_args (arg:args) srcs objs
  | looks_like_an_input arg = partition_args args ((arg,Nothing):srcs) objs
  | otherwise               = partition_args args srcs (arg:objs)

    {-
      We split out the object files (.o, .dll) and add them
      to v_Ld_inputs for use by the linker.<commit_msg>Don't start a GHC session before answering --version/--numeric-version This also fixes bootstrapping issues, as when bootstrapping we don't have a package.conf when we run configure, so it fails to work out what version of GHC it is which causes breakage later on.<commit_after>{-# OPTIONS -fno-warn-incomplete-patterns -optc-DNON_POSIX_SOURCE #-}
-----------------------------------------------------------------------------
--
-- GHC Driver program
--
-- (c) The University of Glasgow 2005
--
-----------------------------------------------------------------------------

module Main (main) where

#include "HsVersions.h"

-- The official GHC API
import qualified GHC
import GHC		( Session, DynFlags(..), GhcMode(..), HscTarget(..),
			  LoadHowMuch(..), dopt, DynFlag(..) )
import CmdLineParser

-- Implementations of the various modes (--show-iface, mkdependHS. etc.)
import LoadIface	( showIface )
import HscMain          ( newHscEnv )
import DriverPipeline	( oneShot, compileFile )
import DriverMkDepend	( doMkDependHS )
#ifdef GHCI
import InteractiveUI	( ghciWelcomeMsg, interactiveUI )
#endif

-- Various other random stuff that we need
import Config		( cProjectVersion, cBooterVersion, cProjectName )
import Packages		( dumpPackages )
import DriverPhases	( Phase(..), isSourceFilename, anyHsc,
			  startPhase, isHaskellSrcFilename )
import StaticFlags
import DynFlags         ( defaultDynFlags )
import BasicTypes	( failed )
import ErrUtils		( putMsg )
import FastString	( getFastStringTable, isZEncoded, hasZEncoding )
import Outputable
import Util
import Panic

-- Standard Haskell libraries
import Control.Exception ( throwDyn )
import System.IO
import System.Directory	( doesDirectoryExist )
import System.Environment
import System.Exit
import Control.Monad
import Data.List
import Data.Maybe

-----------------------------------------------------------------------------
-- ToDo:

-- time commands when run with -v
-- user ways
-- Win32 support: proper signal handling
-- reading the package configuration file is too slow
-- -K<size>

-----------------------------------------------------------------------------
-- GHC's command-line interface

main =
  GHC.defaultErrorHandler defaultDynFlags $ do
  
  -- 1. extract the -B flag from the args
  argv0 <- getArgs

  let
        (minusB_args, argv1) = partition (prefixMatch "-B") argv0
        mbMinusB | null minusB_args = Nothing
                 | otherwise = Just (drop 2 (last minusB_args))

  argv2 <- parseStaticFlags argv1

  -- 2. Parse the "mode" flags (--make, --interactive etc.)
  (cli_mode, argv3) <- parseModeFlags argv2

  -- If all we want to do is to show the version number then do it
  -- now, before we start a GHC session etc.
  -- If we do it later then bootstrapping gets confused as it tries
  -- to find out what version of GHC it's using before package.conf
  -- exists, so starting the session fails.
  case cli_mode of
    ShowVersion     -> do showVersion
                          exitWith ExitSuccess
    ShowNumVersion  -> do putStrLn cProjectVersion
                          exitWith ExitSuccess
    _               -> return ()

  let mode = case cli_mode of
		DoInteractive	-> Interactive
		DoEval _	-> Interactive
		DoMake		-> BatchCompile
		DoMkDependHS	-> MkDepend
		_		-> OneShot

  -- start our GHC session
  session <- GHC.newSession mode mbMinusB

  dflags0 <- GHC.getSessionDynFlags session

  -- set the default HscTarget.  The HscTarget can be further
  -- adjusted on a module by module basis, using only the -fvia-C and
  -- -fasm flags.  If the default HscTarget is not HscC or HscAsm,
  -- -fvia-C and -fasm have no effect.
  let lang = case cli_mode of 
		 DoInteractive  -> HscInterpreted
		 DoEval _	-> HscInterpreted
		 _other		-> hscTarget dflags0

  let dflags1 = dflags0{ ghcMode = mode,
                  	 hscTarget  = lang,
			 -- leave out hscOutName for now
	                 hscOutName = panic "Main.main:hscOutName not set",
		  	 verbosity = case cli_mode of
				 	 DoEval _ -> 0
				 	 _other   -> 1
			}

	-- The rest of the arguments are "dynamic"
	-- Leftover ones are presumably files
  (dflags, fileish_args) <- GHC.parseDynamicFlags dflags1 argv3

	-- make sure we clean up after ourselves
  GHC.defaultCleanupHandler dflags $ do

	-- Display banner
  showBanner cli_mode dflags

  -- we've finished manipulating the DynFlags, update the session
  GHC.setSessionDynFlags session dflags
  dflags <- GHC.getSessionDynFlags session

  let
     -- To simplify the handling of filepaths, we normalise all filepaths right 
     -- away - e.g., for win32 platforms, backslashes are converted
     -- into forward slashes.
    normal_fileish_paths = map normalisePath fileish_args
    (srcs, objs)         = partition_args normal_fileish_paths [] []

  -- Note: have v_Ld_inputs maintain the order in which 'objs' occurred on 
  --       the command-line.
  mapM_ (consIORef v_Ld_inputs) (reverse objs)

	---------------- Display configuration -----------
  when (verbosity dflags >= 4) $
	dumpPackages dflags

  when (verbosity dflags >= 3) $ do
	hPutStrLn stderr ("Hsc static flags: " ++ unwords staticFlags)

	---------------- Final sanity checking -----------
  checkOptions cli_mode dflags srcs objs

	---------------- Do the business -----------
  case cli_mode of
    ShowUsage       -> showGhcUsage dflags cli_mode
    PrintLibdir     -> putStrLn (topDir dflags)
    ShowVersion     -> panic "ShowVersion should already have been handled"
    ShowNumVersion  -> panic "ShowNumVersion should already have been handled"
    ShowInterface f -> doShowIface dflags f
    DoMake          -> doMake session srcs
    DoMkDependHS    -> doMkDependHS session (map fst srcs)
    StopBefore p    -> oneShot dflags p srcs
    DoInteractive   -> interactiveUI session srcs Nothing
    DoEval expr     -> interactiveUI session srcs (Just expr)

  dumpFinalStats dflags
  exitWith ExitSuccess

#ifndef GHCI
interactiveUI _ _ _ = 
  throwDyn (CmdLineError "not built for interactive use")
#endif

-- -----------------------------------------------------------------------------
-- Splitting arguments into source files and object files.  This is where we
-- interpret the -x <suffix> option, and attach a (Maybe Phase) to each source
-- file indicating the phase specified by the -x option in force, if any.

partition_args [] srcs objs = (reverse srcs, reverse objs)
partition_args ("-x":suff:args) srcs objs
  | "none" <- suff	= partition_args args srcs objs
  | StopLn <- phase	= partition_args args srcs (slurp ++ objs)
  | otherwise		= partition_args rest (these_srcs ++ srcs) objs
	where phase = startPhase suff
	      (slurp,rest) = break (== "-x") args 
	      these_srcs = zip slurp (repeat (Just phase))
partition_args (arg:args) srcs objs
  | looks_like_an_input arg = partition_args args ((arg,Nothing):srcs) objs
  | otherwise               = partition_args args srcs (arg:objs)

    {-
      We split out the object files (.o, .dll) and add them
      to v_Ld_inputs for use by the linker.
{'fraction_non_alphanumeric': 0.14425483503981798, 'fraction_numerical': 0.004247250663632916, 'mean_word_length': 2.3281171125694096, 'pattern_counts': {'":': 2, '<': 25, '<?xml version=': 0, '>': 54, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7518266', 'n_tokens_mistral': 4024, 'n_tokens_neox': 3773, 'n_words': 1332}