[project @ 2001-01-25 17:54:24 by simonpj]
[ghc-hetmet.git] / ghc / compiler / main / CmdLineOpts.lhs
1 %
2 % (c) The University of Glasgow, 1996-2000
3 %
4 \section[CmdLineOpts]{Things to do with command-line options}
5
6 \begin{code}
7
8 module CmdLineOpts (
9         CoreToDo(..),
10         SimplifierSwitch(..), isAmongSimpl,
11         StgToDo(..),
12         SwitchResult(..),
13
14         HscLang(..),
15         DynFlag(..),    -- needed non-abstractly by DriverFlags
16         DynFlags(..),
17         defaultDynFlags,
18
19         v_Static_hsc_opts,
20
21         intSwitchSet,
22         switchIsOn,
23         isStaticHscFlag,
24
25         opt_PprStyle_NoPrags,
26         opt_PprStyle_RawTypes,
27         opt_PprUserLength,
28         opt_PprStyle_Debug,
29
30         dopt,
31
32         -- other dynamic flags
33         dopt_CoreToDo,
34         dopt_StgToDo,
35         dopt_HscLang,
36         dopt_OutName,
37
38         -- profiling opts
39         opt_AutoSccsOnAllToplevs,
40         opt_AutoSccsOnExportedToplevs,
41         opt_AutoSccsOnIndividualCafs,
42         opt_AutoSccsOnDicts,
43         opt_SccProfilingOn,
44         opt_DoTickyProfiling,
45
46         -- language opts
47         opt_AllStrict,
48         opt_DictsStrict,
49         opt_MaxContextReductionDepth,
50         opt_IrrefutableTuples,
51         opt_NumbersStrict,
52         opt_Parallel,
53         opt_SMP,
54         opt_NoMonomorphismRestriction,
55
56         -- optimisation opts
57         opt_NoMethodSharing,
58         opt_DoSemiTagging,
59         opt_FoldrBuildOn,
60         opt_LiberateCaseThreshold,
61         opt_StgDoLetNoEscapes,
62         opt_UnfoldCasms,
63         opt_UsageSPOn,
64         opt_UnboxStrictFields,
65         opt_SimplNoPreInlining,
66         opt_SimplDoEtaReduction,
67         opt_SimplDoLambdaEtaExpansion,
68         opt_SimplCaseOfCase,
69         opt_SimplCaseMerge,
70         opt_SimplPedanticBottoms,
71         opt_SimplExcessPrecision,
72
73         -- Unfolding control
74         opt_UF_HiFileThreshold,
75         opt_UF_CreationThreshold,
76         opt_UF_UseThreshold,
77         opt_UF_FunAppDiscount,
78         opt_UF_KeenessFactor,
79         opt_UF_UpdateInPlace,
80         opt_UF_CheapOp,
81         opt_UF_DearOp,
82
83         -- misc opts
84         opt_InPackage,
85         opt_EmitCExternDecls,
86         opt_EnsureSplittableC,
87         opt_GranMacros,
88         opt_HiVersion,
89         opt_HistorySize,
90         opt_IgnoreAsserts,
91         opt_IgnoreIfacePragmas,
92         opt_NoHiCheck,
93         opt_OmitBlackHoling,
94         opt_OmitInterfacePragmas,
95         opt_NoPruneTyDecls,
96         opt_NoPruneDecls,
97         opt_Static,
98         opt_Unregisterised
99     ) where
100
101 #include "HsVersions.h"
102
103 import Array    ( array, (//) )
104 import GlaExts
105 import IOExts   ( IORef, readIORef )
106 import Constants        -- Default values for some flags
107 import Util
108 import FastTypes
109 import Config
110
111 import Maybes           ( firstJust )
112 import Panic            ( panic )
113
114 #if __GLASGOW_HASKELL__ < 301
115 import ArrBase  ( Array(..) )
116 #else
117 import PrelArr  ( Array(..) )
118 #endif
119 \end{code}
120
121 %************************************************************************
122 %*                                                                      *
123 \subsection{Command-line options}
124 %*                                                                      *
125 %************************************************************************
126
127 The hsc command-line options are split into two categories:
128
129   - static flags
130   - dynamic flags
131
132 Static flags are represented by top-level values of type Bool or Int,
133 for example.  They therefore have the same value throughout the
134 invocation of hsc.
135
136 Dynamic flags are represented by an abstract type, DynFlags, which is
137 passed into hsc by the compilation manager for every compilation.
138 Dynamic flags are those that change on a per-compilation basis,
139 perhaps because they may be present in the OPTIONS pragma at the top
140 of a module.
141
142 Other flag-related blurb:
143
144 A list of {\em ToDo}s is things to be done in a particular part of
145 processing.  A (fictitious) example for the Core-to-Core simplifier
146 might be: run the simplifier, then run the strictness analyser, then
147 run the simplifier again (three ``todos'').
148
149 There are three ``to-do processing centers'' at the moment.  In the
150 main loop (\tr{main/Main.lhs}), in the Core-to-Core processing loop
151 (\tr{simplCore/SimplCore.lhs), and in the STG-to-STG processing loop
152 (\tr{simplStg/SimplStg.lhs}).
153
154 %************************************************************************
155 %*                                                                      *
156 \subsection{Datatypes associated with command-line options}
157 %*                                                                      *
158 %************************************************************************
159
160 \begin{code}
161 data SwitchResult
162   = SwBool      Bool            -- on/off
163   | SwString    FAST_STRING     -- nothing or a String
164   | SwInt       Int             -- nothing or an Int
165 \end{code}
166
167 \begin{code}
168 data CoreToDo           -- These are diff core-to-core passes,
169                         -- which may be invoked in any order,
170                         -- as many times as you like.
171
172   = CoreDoSimplify      -- The core-to-core simplifier.
173         (SimplifierSwitch -> SwitchResult)
174                         -- Each run of the simplifier can take a different
175                         -- set of simplifier-specific flags.
176   | CoreDoFloatInwards
177   | CoreDoFloatOutwards Bool    -- True <=> float lambdas to top level
178   | CoreLiberateCase
179   | CoreDoPrintCore
180   | CoreDoStaticArgs
181   | CoreDoStrictness
182   | CoreDoWorkerWrapper
183   | CoreDoSpecialising
184   | CoreDoUSPInf
185   | CoreDoCPResult
186   | CoreDoGlomBinds
187   | CoreCSE
188
189   | CoreDoNothing        -- useful when building up lists of these things
190 \end{code}
191
192 \begin{code}
193 data StgToDo
194   = StgDoMassageForProfiling  -- should be (next to) last
195   -- There's also setStgVarInfo, but its absolute "lastness"
196   -- is so critical that it is hardwired in (no flag).
197   | D_stg_stats
198 \end{code}
199
200 \begin{code}
201 data SimplifierSwitch
202   = MaxSimplifierIterations Int
203   | SimplInlinePhase Int
204   | DontApplyRules
205   | NoCaseOfCase
206   | SimplLetToCase
207 \end{code}
208
209 %************************************************************************
210 %*                                                                      *
211 \subsection{Dynamic command-line options}
212 %*                                                                      *
213 %************************************************************************
214
215 \begin{code}
216 data DynFlag
217
218    -- debugging flags
219    = Opt_D_dump_absC
220    | Opt_D_dump_asm
221    | Opt_D_dump_cpranal
222    | Opt_D_dump_deriv
223    | Opt_D_dump_ds
224    | Opt_D_dump_flatC
225    | Opt_D_dump_foreign
226    | Opt_D_dump_inlinings
227    | Opt_D_dump_occur_anal
228    | Opt_D_dump_parsed
229    | Opt_D_dump_realC
230    | Opt_D_dump_rn
231    | Opt_D_dump_simpl
232    | Opt_D_dump_simpl_iterations
233    | Opt_D_dump_spec
234    | Opt_D_dump_sat
235    | Opt_D_dump_stg
236    | Opt_D_dump_stranal
237    | Opt_D_dump_tc
238    | Opt_D_dump_types
239    | Opt_D_dump_rules
240    | Opt_D_dump_usagesp
241    | Opt_D_dump_cse
242    | Opt_D_dump_worker_wrapper
243    | Opt_D_dump_rn_trace
244    | Opt_D_dump_rn_stats
245    | Opt_D_dump_stix
246    | Opt_D_dump_simpl_stats
247    | Opt_D_dump_BCOs
248    | Opt_D_source_stats
249    | Opt_D_verbose_core2core
250    | Opt_D_verbose_stg2stg
251    | Opt_D_dump_hi
252    | Opt_D_dump_hi_diffs
253    | Opt_D_dump_minimal_imports
254    | Opt_DoCoreLinting
255    | Opt_DoStgLinting
256    | Opt_DoUSPLinting
257
258    | Opt_WarnDuplicateExports
259    | Opt_WarnHiShadows
260    | Opt_WarnIncompletePatterns
261    | Opt_WarnMissingFields
262    | Opt_WarnMissingMethods
263    | Opt_WarnMissingSigs
264    | Opt_WarnNameShadowing
265    | Opt_WarnOverlappingPatterns
266    | Opt_WarnSimplePatterns
267    | Opt_WarnTypeDefaults
268    | Opt_WarnUnusedBinds
269    | Opt_WarnUnusedImports
270    | Opt_WarnUnusedMatches
271    | Opt_WarnDeprecations
272
273    -- language opts
274    | Opt_AllowOverlappingInstances
275    | Opt_AllowUndecidableInstances
276    | Opt_GlasgowExts
277    | Opt_Generics
278    | Opt_NoImplicitPrelude 
279
280    -- misc
281    | Opt_ReportCompile
282    deriving (Eq)
283
284 data DynFlags = DynFlags {
285   coreToDo              :: [CoreToDo],
286   stgToDo               :: [StgToDo],
287   hscLang               :: HscLang,
288   hscOutName            :: String,      -- name of the output file
289   verbosity             :: Int,         -- verbosity level
290   cppFlag               :: Bool,        -- preprocess with cpp?
291   stolen_x86_regs       :: Int,         
292   cmdlineHcIncludes     :: [String],    -- -#includes
293
294   -- options for particular phases
295   opt_L                 :: [String],
296   opt_P                 :: [String],
297   opt_c                 :: [String],
298   opt_a                 :: [String],
299   opt_m                 :: [String],
300
301   -- hsc dynamic flags
302   flags                 :: [DynFlag]
303  }
304
305 defaultDynFlags = DynFlags {
306   coreToDo = [], stgToDo = [], 
307   hscLang = HscC, 
308   hscOutName = "", 
309   verbosity = 0, 
310   cppFlag               = False,
311   stolen_x86_regs       = 4,
312   cmdlineHcIncludes     = [],
313   opt_L                 = [],
314   opt_P                 = [],
315   opt_c                 = [],
316   opt_a                 = [],
317   opt_m                 = [],
318   flags = []
319   }
320
321 {- 
322     Verbosity levels:
323         
324     0   |   print errors & warnings only
325     1   |   minimal verbosity: print "compiling M ... done." for each module.
326     2   |   equivalent to -dshow-passes
327     3   |   equivalent to existing "ghc -v"
328     4   |   "ghc -v -ddump-most"
329     5   |   "ghc -v -ddump-all"
330 -}
331
332 dopt :: DynFlag -> DynFlags -> Bool
333 dopt f dflags  = f `elem` (flags dflags)
334
335 dopt_CoreToDo :: DynFlags -> [CoreToDo]
336 dopt_CoreToDo = coreToDo
337
338 dopt_StgToDo :: DynFlags -> [StgToDo]
339 dopt_StgToDo = stgToDo
340
341 dopt_OutName :: DynFlags -> String
342 dopt_OutName = hscOutName
343
344 data HscLang
345   = HscC
346   | HscAsm
347   | HscJava
348   | HscInterpreted
349     deriving (Eq, Show)
350
351 dopt_HscLang :: DynFlags -> HscLang
352 dopt_HscLang = hscLang
353 \end{code}
354
355 %************************************************************************
356 %*                                                                      *
357 \subsection{Classifying command-line options}
358 %*                                                                      *
359 %************************************************************************
360
361 \begin{code}
362 -- v_Statis_hsc_opts is here to avoid a circular dependency with
363 -- main/DriverState.
364 GLOBAL_VAR(v_Static_hsc_opts, [], [String])
365
366 lookUp           :: FAST_STRING -> Bool
367 lookup_int       :: String -> Maybe Int
368 lookup_def_int   :: String -> Int -> Int
369 lookup_def_float :: String -> Float -> Float
370 lookup_str       :: String -> Maybe String
371
372 unpacked_static_opts = unsafePerformIO (readIORef v_Static_hsc_opts)
373 packed_static_opts   = map _PK_ unpacked_static_opts
374
375 lookUp     sw = sw `elem` packed_static_opts
376         
377 lookup_str sw = firstJust (map (startsWith sw) unpacked_static_opts)
378
379 lookup_int sw = case (lookup_str sw) of
380                   Nothing -> Nothing
381                   Just xx -> Just (read xx)
382
383 lookup_def_int sw def = case (lookup_str sw) of
384                             Nothing -> def              -- Use default
385                             Just xx -> read xx
386
387 lookup_def_float sw def = case (lookup_str sw) of
388                             Nothing -> def              -- Use default
389                             Just xx -> read xx
390
391
392 {-
393  Putting the compiler options into temporary at-files
394  may turn out to be necessary later on if we turn hsc into
395  a pure Win32 application where I think there's a command-line
396  length limit of 255. unpacked_opts understands the @ option.
397
398 unpacked_opts :: [String]
399 unpacked_opts =
400   concat $
401   map (expandAts) $
402   map _UNPK_ argv  -- NOT ARGV any more: v_Static_hsc_opts
403   where
404    expandAts ('@':fname) = words (unsafePerformIO (readFile fname))
405    expandAts l = [l]
406 -}
407 \end{code}
408
409 %************************************************************************
410 %*                                                                      *
411 \subsection{Static options}
412 %*                                                                      *
413 %************************************************************************
414
415 \begin{code}
416 -- debugging opts
417 opt_PprStyle_NoPrags            = lookUp  SLIT("-dppr-noprags")
418 opt_PprStyle_Debug              = lookUp  SLIT("-dppr-debug")
419 opt_PprStyle_RawTypes           = lookUp  SLIT("-dppr-rawtypes")
420 opt_PprUserLength               = lookup_def_int "-dppr-user-length" 5 --ToDo: give this a name
421
422 -- profiling opts
423 opt_AutoSccsOnAllToplevs        = lookUp  SLIT("-fauto-sccs-on-all-toplevs")
424 opt_AutoSccsOnExportedToplevs   = lookUp  SLIT("-fauto-sccs-on-exported-toplevs")
425 opt_AutoSccsOnIndividualCafs    = lookUp  SLIT("-fauto-sccs-on-individual-cafs")
426 opt_AutoSccsOnDicts             = lookUp  SLIT("-fauto-sccs-on-dicts")
427 opt_SccProfilingOn              = lookUp  SLIT("-fscc-profiling")
428 opt_DoTickyProfiling            = lookUp  SLIT("-fticky-ticky")
429
430 -- language opts
431 opt_AllStrict                   = lookUp  SLIT("-fall-strict")
432 opt_NoMonomorphismRestriction   = lookUp  SLIT("-fno-monomorphism-restriction")
433 opt_DictsStrict                 = lookUp  SLIT("-fdicts-strict")
434 opt_IrrefutableTuples           = lookUp  SLIT("-firrefutable-tuples")
435 opt_MaxContextReductionDepth    = lookup_def_int "-fcontext-stack" mAX_CONTEXT_REDUCTION_DEPTH
436 opt_NumbersStrict               = lookUp  SLIT("-fnumbers-strict")
437 opt_Parallel                    = lookUp  SLIT("-fparallel")
438 opt_SMP                         = lookUp  SLIT("-fsmp")
439
440 -- optimisation opts
441 opt_NoMethodSharing             = lookUp  SLIT("-fno-method-sharing")
442 opt_DoSemiTagging               = lookUp  SLIT("-fsemi-tagging")
443 opt_FoldrBuildOn                = lookUp  SLIT("-ffoldr-build-on")
444 opt_LiberateCaseThreshold       = lookup_def_int "-fliberate-case-threshold" (10::Int)
445 opt_StgDoLetNoEscapes           = lookUp  SLIT("-flet-no-escape")
446 opt_UnfoldCasms                 = lookUp SLIT("-funfold-casms-in-hi-file")
447 opt_UsageSPOn                   = lookUp  SLIT("-fusagesp-on")
448 opt_UnboxStrictFields           = lookUp  SLIT("-funbox-strict-fields")
449
450 {-
451    The optional '-inpackage=P' flag tells what package
452    we are compiling this module for.
453    The Prelude, for example is compiled with '-package prelude'
454 -}
455 opt_InPackage                   = case lookup_str "-inpackage=" of
456                                     Just p  -> _PK_ p
457                                     Nothing -> SLIT("Main")     -- The package name if none is specified
458
459 opt_EmitCExternDecls            = lookUp  SLIT("-femit-extern-decls")
460 opt_EnsureSplittableC           = lookUp  SLIT("-fglobalise-toplev-names")
461 opt_GranMacros                  = lookUp  SLIT("-fgransim")
462 opt_HiVersion                   = read cProjectVersionInt :: Int
463 opt_HistorySize                 = lookup_def_int "-fhistory-size" 20
464 opt_IgnoreAsserts               = lookUp  SLIT("-fignore-asserts")
465 opt_IgnoreIfacePragmas          = lookUp  SLIT("-fignore-interface-pragmas")
466 opt_NoHiCheck                   = lookUp  SLIT("-fno-hi-version-check")
467 opt_OmitBlackHoling             = lookUp  SLIT("-dno-black-holing")
468 opt_OmitInterfacePragmas        = lookUp  SLIT("-fomit-interface-pragmas")
469
470 -- Simplifier switches
471 opt_SimplNoPreInlining          = lookUp SLIT("-fno-pre-inlining")
472         -- NoPreInlining is there just to see how bad things
473         -- get if you don't do it!
474 opt_SimplDoEtaReduction         = lookUp SLIT("-fdo-eta-reduction")
475 opt_SimplDoLambdaEtaExpansion   = lookUp SLIT("-fdo-lambda-eta-expansion")
476 opt_SimplCaseOfCase             = lookUp SLIT("-fcase-of-case")
477 opt_SimplCaseMerge              = lookUp SLIT("-fcase-merge")
478 opt_SimplPedanticBottoms        = lookUp SLIT("-fpedantic-bottoms")
479 opt_SimplExcessPrecision        = lookUp SLIT("-fexcess-precision")
480
481 -- Unfolding control
482 opt_UF_HiFileThreshold          = lookup_def_int "-funfolding-interface-threshold" (45::Int)
483 opt_UF_CreationThreshold        = lookup_def_int "-funfolding-creation-threshold"  (45::Int)
484 opt_UF_UseThreshold             = lookup_def_int "-funfolding-use-threshold"       (8::Int)     -- Discounts can be big
485 opt_UF_FunAppDiscount           = lookup_def_int "-funfolding-fun-discount"        (6::Int)     -- It's great to inline a fn
486 opt_UF_KeenessFactor            = lookup_def_float "-funfolding-keeness-factor"    (1.5::Float)
487 opt_UF_UpdateInPlace            = lookUp  SLIT("-funfolding-update-in-place")
488
489 opt_UF_CheapOp  = ( 1 :: Int)   -- Only one instruction; and the args are charged for
490 opt_UF_DearOp   = ( 4 :: Int)
491                         
492 opt_NoPruneDecls                = lookUp SLIT("-fno-prune-decls")
493 opt_NoPruneTyDecls              = lookUp SLIT("-fno-prune-tydecls")
494 opt_Static                      = lookUp SLIT("-static")
495 opt_Unregisterised              = lookUp SLIT("-funregisterised")
496 \end{code}
497
498 %************************************************************************
499 %*                                                                      *
500 \subsection{List of static hsc flags}
501 %*                                                                      *
502 %************************************************************************
503
504 \begin{code}
505 isStaticHscFlag f =
506   f `elem` [
507         "fauto-sccs-on-all-toplevs",
508         "fauto-sccs-on-exported-toplevs",
509         "fauto-sccs-on-individual-cafs",
510         "fauto-sccs-on-dicts",
511         "fscc-profiling",
512         "fticky-ticky",
513         "fall-strict",
514         "fdicts-strict",
515         "firrefutable-tuples",
516         "fnumbers-strict",
517         "fparallel",
518         "fsmp",
519         "fsemi-tagging",
520         "ffoldr-build-on",
521         "flet-no-escape",
522         "funfold-casms-in-hi-file",
523         "fusagesp-on",
524         "funbox-strict-fields",
525         "femit-extern-decls",
526         "fglobalise-toplev-names",
527         "fgransim",
528         "fignore-asserts",
529         "fignore-interface-pragmas",
530         "fno-hi-version-check",
531         "dno-black-holing",
532         "fomit-interface-pragmas",
533         "fno-pre-inlining",
534         "fdo-eta-reduction",
535         "fdo-lambda-eta-expansion",
536         "fcase-of-case",
537         "fcase-merge",
538         "fpedantic-bottoms",
539         "fexcess-precision",
540         "funfolding-update-in-place",
541         "freport-compile",
542         "fno-prune-decls",
543         "fno-prune-tydecls",
544         "static",
545         "funregisterised"
546         ]
547   || any (flip prefixMatch f) [
548         "fcontext-stack",
549         "fliberate-case-threshold",
550         "fhistory-size",
551         "funfolding-interface-threshold",
552         "funfolding-creation-threshold",
553         "funfolding-use-threshold",
554         "funfolding-fun-discount",
555         "funfolding-keeness-factor"
556      ]
557 \end{code}
558
559 %************************************************************************
560 %*                                                                      *
561 \subsection{Switch ordering}
562 %*                                                                      *
563 %************************************************************************
564
565 These things behave just like enumeration types.
566
567 \begin{code}
568 instance Eq SimplifierSwitch where
569     a == b = tagOf_SimplSwitch a ==# tagOf_SimplSwitch b
570
571 instance Ord SimplifierSwitch where
572     a <  b  = tagOf_SimplSwitch a <# tagOf_SimplSwitch b
573     a <= b  = tagOf_SimplSwitch a <=# tagOf_SimplSwitch b
574
575
576 tagOf_SimplSwitch (SimplInlinePhase _)          = _ILIT(1)
577 tagOf_SimplSwitch (MaxSimplifierIterations _)   = _ILIT(2)
578 tagOf_SimplSwitch DontApplyRules                = _ILIT(3)
579 tagOf_SimplSwitch SimplLetToCase                = _ILIT(4)
580 tagOf_SimplSwitch NoCaseOfCase                  = _ILIT(5)
581
582 -- If you add anything here, be sure to change lAST_SIMPL_SWITCH_TAG, too!
583
584 lAST_SIMPL_SWITCH_TAG = 5
585 \end{code}
586
587 %************************************************************************
588 %*                                                                      *
589 \subsection{Switch lookup}
590 %*                                                                      *
591 %************************************************************************
592
593 \begin{code}
594 isAmongSimpl :: [SimplifierSwitch] -> SimplifierSwitch -> SwitchResult
595 isAmongSimpl on_switches                -- Switches mentioned later occur *earlier*
596                                         -- in the list; defaults right at the end.
597   = let
598         tidied_on_switches = foldl rm_dups [] on_switches
599                 -- The fold*l* ensures that we keep the latest switches;
600                 -- ie the ones that occur earliest in the list.
601
602         sw_tbl :: Array Int SwitchResult
603         sw_tbl = (array (0, lAST_SIMPL_SWITCH_TAG) -- bounds...
604                         all_undefined)
605                  // defined_elems
606
607         all_undefined = [ (i, SwBool False) | i <- [0 .. lAST_SIMPL_SWITCH_TAG ] ]
608
609         defined_elems = map mk_assoc_elem tidied_on_switches
610     in
611     -- (avoid some unboxing, bounds checking, and other horrible things:)
612 #if __GLASGOW_HASKELL__ < 405
613     case sw_tbl of { Array bounds_who_needs_'em stuff ->
614 #else
615     case sw_tbl of { Array _ _ stuff ->
616 #endif
617     \ switch ->
618         case (indexArray# stuff (tagOf_SimplSwitch switch)) of
619 #if __GLASGOW_HASKELL__ < 400
620           Lift v -> v
621 #elif __GLASGOW_HASKELL__ < 403
622           (# _, v #) -> v
623 #else
624           (# v #) -> v
625 #endif
626     }
627   where
628     mk_assoc_elem k@(MaxSimplifierIterations lvl)
629         = (iBox (tagOf_SimplSwitch k), SwInt lvl)
630     mk_assoc_elem k@(SimplInlinePhase n)
631         = (iBox (tagOf_SimplSwitch k), SwInt n)
632     mk_assoc_elem k
633         = (iBox (tagOf_SimplSwitch k), SwBool True) -- I'm here, Mom!
634
635     -- cannot have duplicates if we are going to use the array thing
636     rm_dups switches_so_far switch
637       = if switch `is_elem` switches_so_far
638         then switches_so_far
639         else switch : switches_so_far
640       where
641         sw `is_elem` []     = False
642         sw `is_elem` (s:ss) = (tagOf_SimplSwitch sw) ==# (tagOf_SimplSwitch s)
643                             || sw `is_elem` ss
644 \end{code}
645
646
647 %************************************************************************
648 %*                                                                      *
649 \subsection{Misc functions for command-line options}
650 %*                                                                      *
651 %************************************************************************
652
653
654 \begin{code}
655 switchIsOn :: (switch -> SwitchResult) -> switch -> Bool
656
657 switchIsOn lookup_fn switch
658   = case (lookup_fn switch) of
659       SwBool False -> False
660       _            -> True
661
662 intSwitchSet :: (switch -> SwitchResult)
663              -> (Int -> switch)
664              -> Maybe Int
665
666 intSwitchSet lookup_fn switch
667   = case (lookup_fn (switch (panic "intSwitchSet"))) of
668       SwInt int -> Just int
669       _         -> Nothing
670 \end{code}
671
672 \begin{code}
673 startsWith :: String -> String -> Maybe String
674 -- startsWith pfx (pfx++rest) = Just rest
675
676 startsWith []     str = Just str
677 startsWith (c:cs) (s:ss)
678   = if c /= s then Nothing else startsWith cs ss
679 startsWith  _     []  = Nothing
680
681 endsWith  :: String -> String -> Maybe String
682 endsWith cs ss
683   = case (startsWith (reverse cs) (reverse ss)) of
684       Nothing -> Nothing
685       Just rs -> Just (reverse rs)
686 \end{code}