StaticFlags.hs 14.4 KB
Newer Older
1
2
3
{-# OPTIONS -fno-cse #-}
-- -fno-cse is needed for GLOBAL_VAR's to behave properly

4
5
6
7
8
9
10
11
12
13
14
15
16
-----------------------------------------------------------------------------
--
-- Static flags
--
-- Static flags can only be set once, on the command-line.  Inside GHC,
-- each static flag corresponds to a top-level value, usually of type Bool.
--
-- (c) The University of Glasgow 2005
--
-----------------------------------------------------------------------------

module StaticFlags (
	staticFlags,
17
        initStaticOpts,
18
19

	-- Ways
20
	WayName(..), v_Ways, v_Build_tag, v_RTS_Build_tag, isRTSWay,
21
22
23

	-- Output style options
	opt_PprUserLength,
24
	opt_SuppressUniques,
25
	opt_PprStyle_Debug,
Simon Marlow's avatar
Simon Marlow committed
26
        opt_NoDebugOutput,
27
28
29
30

	-- profiling opts
	opt_SccProfilingOn,

andy@galois.com's avatar
andy@galois.com committed
31
32
33
        -- Hpc opts
	opt_Hpc,

34
35
36
37
38
39
	-- language opts
	opt_DictsStrict,
	opt_IrrefutableTuples,
	opt_Parallel,

	-- optimisation opts
40
	opt_DsMultiTyVar,
41
	opt_NoStateHack,
42
        opt_SimpleListLiterals,
43
	opt_SpecInlineJoinPoints,
44
45
46
47
48
49
50
51
52
53
54
55
	opt_CprOff,
	opt_SimplNoPreInlining,
	opt_SimplExcessPrecision,
	opt_MaxWorkerArgs,

	-- Unfolding control
	opt_UF_CreationThreshold,
	opt_UF_UseThreshold,
	opt_UF_FunAppDiscount,
	opt_UF_KeenessFactor,
	opt_UF_DearOp,

dias@eecs.harvard.edu's avatar
dias@eecs.harvard.edu committed
56
57
58
	-- Optimization fuel controls
	opt_Fuel,

59
60
61
62
	-- Related to linking
	opt_PIC,
	opt_Static,

63
64
65
66
67
68
69
70
71
72
	-- misc opts
	opt_IgnoreDotGhci,
	opt_ErrorSpans,
	opt_GranMacros,
	opt_HiVersion,
	opt_HistorySize,
	opt_OmitBlackHoling,
	opt_Unregisterised,
	opt_EmitExternalCore,
	v_Ld_inputs,
73
	tablesNextToCode,
74
        opt_StubDeadValues,
75
76
77

    -- For the parser
    addOpt, removeOpt, addWay, findBuildTag, v_opt_C_ready
78
79
80
81
  ) where

#include "HsVersions.h"

82
import Config
83
import FastString
84
85
import Util
import Maybes		( firstJust )
86
import Panic
87

Simon Marlow's avatar
Simon Marlow committed
88
89
import Data.IORef
import System.IO.Unsafe	( unsafePerformIO )
90
import Data.List
91
92
93
94

-----------------------------------------------------------------------------
-- Static flags

95
96
initStaticOpts :: IO ()
initStaticOpts = writeIORef v_opt_C_ready True
97

Ian Lynagh's avatar
Ian Lynagh committed
98
addOpt :: String -> IO ()
99
100
addOpt = consIORef v_opt_C

Ian Lynagh's avatar
Ian Lynagh committed
101
addWay :: WayName -> IO ()
102
103
addWay = consIORef v_Ways

Ian Lynagh's avatar
Ian Lynagh committed
104
removeOpt :: String -> IO ()
105
106
107
108
109
110
111
112
113
114
115
116
removeOpt f = do
  fs <- readIORef v_opt_C
  writeIORef v_opt_C $! filter (/= f) fs    

lookUp	       	 :: FastString -> Bool
lookup_def_int   :: String -> Int -> Int
lookup_def_float :: String -> Float -> Float
lookup_str       :: String -> Maybe String

-- holds the static opts while they're being collected, before
-- being unsafely read by unpacked_static_opts below.
GLOBAL_VAR(v_opt_C, defaultStaticOpts, [String])
117
GLOBAL_VAR(v_opt_C_ready, False, Bool)
Ian Lynagh's avatar
Ian Lynagh committed
118
119

staticFlags :: [String]
120
121
122
staticFlags = unsafePerformIO $ do
  ready <- readIORef v_opt_C_ready
  if (not ready)
123
        then panic "Static flags have not been initialised!\n        Please call GHC.newSession or GHC.parseStaticFlags early enough."
124
        else readIORef v_opt_C
125
126

-- -static is the default
Ian Lynagh's avatar
Ian Lynagh committed
127
defaultStaticOpts :: [String]
128
129
defaultStaticOpts = ["-static"]

Ian Lynagh's avatar
Ian Lynagh committed
130
packed_static_opts :: [FastString]
131
132
133
134
135
136
137
packed_static_opts   = map mkFastString staticFlags

lookUp     sw = sw `elem` packed_static_opts
	
-- (lookup_str "foo") looks for the flag -foo=X or -fooX, 
-- and returns the string X
lookup_str sw 
138
   = case firstJust (map (maybePrefixMatch sw) staticFlags) of
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
	Just ('=' : str) -> Just str
	Just str         -> Just str
	Nothing		 -> Nothing	

lookup_def_int sw def = case (lookup_str sw) of
			    Nothing -> def		-- Use default
		  	    Just xx -> try_read sw xx

lookup_def_float sw def = case (lookup_str sw) of
			    Nothing -> def		-- Use default
		  	    Just xx -> try_read sw xx


try_read :: Read a => String -> String -> a
-- (try_read sw str) tries to read s; if it fails, it
-- bleats about flag sw
try_read sw str
  = case reads str of
	((x,_):_) -> x	-- Be forgiving: ignore trailing goop, and alternative parses
	[]	  -> ghcError (UsageError ("Malformed argument " ++ str ++ " for flag " ++ sw))
			-- ToDo: hack alert. We should really parse the arugments
			-- 	 and announce errors in a more civilised way.


{-
 Putting the compiler options into temporary at-files
 may turn out to be necessary later on if we turn hsc into
 a pure Win32 application where I think there's a command-line
 length limit of 255. unpacked_opts understands the @ option.

unpacked_opts :: [String]
unpacked_opts =
  concat $
  map (expandAts) $
  map unpackFS argv  -- NOT ARGV any more: v_Static_hsc_opts
  where
   expandAts ('@':fname) = words (unsafePerformIO (readFile fname))
   expandAts l = [l]
-}

Ian Lynagh's avatar
Ian Lynagh committed
179
opt_IgnoreDotGhci :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
180
opt_IgnoreDotGhci		= lookUp (fsLit "-ignore-dot-ghci")
181
182

-- debugging opts
Ian Lynagh's avatar
Ian Lynagh committed
183
opt_SuppressUniques :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
184
opt_SuppressUniques		= lookUp  (fsLit "-dsuppress-uniques")
dias@eecs.harvard.edu's avatar
dias@eecs.harvard.edu committed
185
opt_PprStyle_Debug  :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
186
opt_PprStyle_Debug		= lookUp  (fsLit "-dppr-debug")
dias@eecs.harvard.edu's avatar
dias@eecs.harvard.edu committed
187
opt_PprUserLength   :: Int
188
opt_PprUserLength	        = lookup_def_int "-dppr-user-length" 5 --ToDo: give this a name
dias@eecs.harvard.edu's avatar
dias@eecs.harvard.edu committed
189
190
opt_Fuel            :: Int
opt_Fuel                        = lookup_def_int "-dopt-fuel" maxBound
Simon Marlow's avatar
Simon Marlow committed
191
192
193
opt_NoDebugOutput   :: Bool
opt_NoDebugOutput               = lookUp  (fsLit "-dno-debug-output")

194
195

-- profiling opts
Ian Lynagh's avatar
Ian Lynagh committed
196
opt_SccProfilingOn :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
197
opt_SccProfilingOn		= lookUp  (fsLit "-fscc-profiling")
andy@galois.com's avatar
andy@galois.com committed
198

199
-- Hpc opts
Ian Lynagh's avatar
Ian Lynagh committed
200
opt_Hpc :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
201
opt_Hpc				= lookUp (fsLit "-fhpc")  
andy@galois.com's avatar
andy@galois.com committed
202

203
-- language opts
Ian Lynagh's avatar
Ian Lynagh committed
204
opt_DictsStrict :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
205
opt_DictsStrict			= lookUp  (fsLit "-fdicts-strict")
Ian Lynagh's avatar
Ian Lynagh committed
206
opt_IrrefutableTuples :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
207
opt_IrrefutableTuples		= lookUp  (fsLit "-firrefutable-tuples")
Ian Lynagh's avatar
Ian Lynagh committed
208
opt_Parallel :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
209
opt_Parallel			= lookUp  (fsLit "-fparallel")
210
211

-- optimisation opts
212
213
214
215
opt_DsMultiTyVar :: Bool
opt_DsMultiTyVar		= not (lookUp (fsLit "-fno-ds-multi-tyvar"))
	-- On by default

Ian Lynagh's avatar
Ian Lynagh committed
216
opt_SpecInlineJoinPoints :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
217
opt_SpecInlineJoinPoints	= lookUp  (fsLit "-fspec-inline-join-points")
218

219
220
221
opt_SimpleListLiterals :: Bool
opt_SimpleListLiterals	        = lookUp  (fsLit "-fsimple-list-literals")

Ian Lynagh's avatar
Ian Lynagh committed
222
opt_NoStateHack :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
223
opt_NoStateHack			= lookUp  (fsLit "-fno-state-hack")
224

Ian Lynagh's avatar
Ian Lynagh committed
225
opt_CprOff :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
226
opt_CprOff			= lookUp  (fsLit "-fcpr-off")
227
	-- Switch off CPR analysis in the new demand analyser
Ian Lynagh's avatar
Ian Lynagh committed
228
opt_MaxWorkerArgs :: Int
229
230
opt_MaxWorkerArgs		= lookup_def_int "-fmax-worker-args" (10::Int)

Ian Lynagh's avatar
Ian Lynagh committed
231
opt_GranMacros :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
232
opt_GranMacros			= lookUp  (fsLit "-fgransim")
Ian Lynagh's avatar
Ian Lynagh committed
233
opt_HiVersion :: Integer
234
opt_HiVersion			= read (cProjectVersionInt ++ cProjectPatchLevel) :: Integer
Ian Lynagh's avatar
Ian Lynagh committed
235
opt_HistorySize :: Int
236
opt_HistorySize			= lookup_def_int "-fhistory-size" 20
Ian Lynagh's avatar
Ian Lynagh committed
237
opt_OmitBlackHoling :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
238
opt_OmitBlackHoling		= lookUp  (fsLit "-dno-black-holing")
239
240
opt_StubDeadValues  :: Bool
opt_StubDeadValues		= lookUp  (fsLit "-dstub-dead-values")
241
242

-- Simplifier switches
Ian Lynagh's avatar
Ian Lynagh committed
243
opt_SimplNoPreInlining :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
244
opt_SimplNoPreInlining		= lookUp  (fsLit "-fno-pre-inlining")
245
246
	-- NoPreInlining is there just to see how bad things
	-- get if you don't do it!
Ian Lynagh's avatar
Ian Lynagh committed
247
opt_SimplExcessPrecision :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
248
opt_SimplExcessPrecision	= lookUp  (fsLit "-fexcess-precision")
249
250

-- Unfolding control
Ian Lynagh's avatar
Ian Lynagh committed
251
opt_UF_CreationThreshold :: Int
252
opt_UF_CreationThreshold	= lookup_def_int "-funfolding-creation-threshold"  (45::Int)
Ian Lynagh's avatar
Ian Lynagh committed
253
opt_UF_UseThreshold :: Int
254
opt_UF_UseThreshold		= lookup_def_int "-funfolding-use-threshold"	   (8::Int)	-- Discounts can be big
Ian Lynagh's avatar
Ian Lynagh committed
255
opt_UF_FunAppDiscount :: Int
256
opt_UF_FunAppDiscount		= lookup_def_int "-funfolding-fun-discount"	   (6::Int)	-- It's great to inline a fn
Ian Lynagh's avatar
Ian Lynagh committed
257
opt_UF_KeenessFactor :: Float
258
259
opt_UF_KeenessFactor		= lookup_def_float "-funfolding-keeness-factor"	   (1.5::Float)

Ian Lynagh's avatar
Ian Lynagh committed
260
opt_UF_DearOp :: Int
261
opt_UF_DearOp   = ( 4 :: Int)
Ian Lynagh's avatar
Ian Lynagh committed
262

dias@eecs.harvard.edu's avatar
dias@eecs.harvard.edu committed
263
264

-- Related to linking
Ian Lynagh's avatar
Ian Lynagh committed
265
opt_PIC :: Bool
266
267
268
#if darwin_TARGET_OS && x86_64_TARGET_ARCH
opt_PIC                         = True
#else
Ian Lynagh's avatar
Ian Lynagh committed
269
opt_PIC                         = lookUp (fsLit "-fPIC")
270
#endif
Ian Lynagh's avatar
Ian Lynagh committed
271
opt_Static :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
272
opt_Static			= lookUp  (fsLit "-static")
Ian Lynagh's avatar
Ian Lynagh committed
273
opt_Unregisterised :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
274
opt_Unregisterised		= lookUp  (fsLit "-funregisterised")
275
276
277
278
279

-- Derived, not a real option.  Determines whether we will be compiling
-- info tables that reside just before the entry code, or with an
-- indirection to the entry code.  See TABLES_NEXT_TO_CODE in 
-- includes/InfoTables.h.
Ian Lynagh's avatar
Ian Lynagh committed
280
tablesNextToCode :: Bool
281
282
283
tablesNextToCode 		= not opt_Unregisterised
		 		  && cGhcEnableTablesNextToCode == "YES"

Ian Lynagh's avatar
Ian Lynagh committed
284
opt_EmitExternalCore :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
285
opt_EmitExternalCore		= lookUp  (fsLit "-fext-core")
286
287

-- Include full span info in error messages, instead of just the start position.
Ian Lynagh's avatar
Ian Lynagh committed
288
opt_ErrorSpans :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
289
opt_ErrorSpans			= lookUp (fsLit "-ferror-spans")
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322


-- object files and libraries to be linked in are collected here.
-- ToDo: perhaps this could be done without a global, it wasn't obvious
-- how to do it though --SDM.
GLOBAL_VAR(v_Ld_inputs,	[],      [String])

-----------------------------------------------------------------------------
-- Ways

-- The central concept of a "way" is that all objects in a given
-- program must be compiled in the same "way".  Certain options change
-- parameters of the virtual machine, eg. profiling adds an extra word
-- to the object header, so profiling objects cannot be linked with
-- non-profiling objects.

-- After parsing the command-line options, we determine which "way" we
-- are building - this might be a combination way, eg. profiling+ticky-ticky.

-- We then find the "build-tag" associated with this way, and this
-- becomes the suffix used to find .hi files and libraries used in
-- this compilation.

GLOBAL_VAR(v_Build_tag, "", String)

-- The RTS has its own build tag, because there are some ways that
-- affect the RTS only.
GLOBAL_VAR(v_RTS_Build_tag, "", String)

data WayName
  = WayThreaded
  | WayDebug
  | WayProf
Simon Marlow's avatar
Simon Marlow committed
323
  | WayEventLog
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  | WayTicky
  | WayPar
  | WayGran
  | WayNDP
  | WayUser_a
  | WayUser_b
  | WayUser_c
  | WayUser_d
  | WayUser_e
  | WayUser_f
  | WayUser_g
  | WayUser_h
  | WayUser_i
  | WayUser_j
  | WayUser_k
  | WayUser_l
  | WayUser_m
  | WayUser_n
  | WayUser_o
  | WayUser_A
  | WayUser_B
  deriving (Eq,Ord)

GLOBAL_VAR(v_Ways, [] ,[WayName])

Ian Lynagh's avatar
Ian Lynagh committed
349
allowed_combination :: [WayName] -> Bool
350
351
352
353
354
355
356
357
358
359
360
361
allowed_combination way = and [ x `allowedWith` y 
			      | x <- way, y <- way, x < y ]
  where
	-- Note ordering in these tests: the left argument is
	-- <= the right argument, according to the Ord instance
	-- on Way above.

	-- debug is allowed with everything
	_ `allowedWith` WayDebug		= True
	WayDebug `allowedWith` _		= True

	WayProf `allowedWith` WayNDP		= True
Simon Marlow's avatar
Simon Marlow committed
362
	WayThreaded `allowedWith` WayProf	= True
Simon Marlow's avatar
Simon Marlow committed
363
	WayThreaded `allowedWith` WayEventLog	= True
364
365
366
367
368
369
	_ `allowedWith` _ 			= False


findBuildTag :: IO [String]  -- new options
findBuildTag = do
  way_names <- readIORef v_Ways
370
  let ws = sort (nub way_names)
371
372

  if not (allowed_combination ws)
373
      then ghcError (CmdLineError $
374
375
376
377
378
379
380
381
382
383
384
385
      		    "combination not supported: "  ++
      		    foldr1 (\a b -> a ++ '/':b) 
      		    (map (wayName . lkupWay) ws))
      else let ways    = map lkupWay ws
      	       tag     = mkBuildTag (filter (not.wayRTSOnly) ways)
      	       rts_tag = mkBuildTag ways
      	       flags   = map wayOpts ways
      	   in do
      	   writeIORef v_Build_tag tag
      	   writeIORef v_RTS_Build_tag rts_tag
      	   return (concat flags)

386
387


388
389
390
mkBuildTag :: [Way] -> String
mkBuildTag ways = concat (intersperse "_" (map wayTag ways))

Ian Lynagh's avatar
Ian Lynagh committed
391
lkupWay :: WayName -> Way
392
393
394
395
396
lkupWay w = 
   case lookup w way_details of
	Nothing -> error "findBuildTag"
	Just details -> details

Ian Lynagh's avatar
Ian Lynagh committed
397
isRTSWay :: WayName -> Bool
398
399
isRTSWay = wayRTSOnly . lkupWay 

400
401
402
403
404
405
406
407
408
409
410
data Way = Way {
  wayTag     :: String,
  wayRTSOnly :: Bool,
  wayName    :: String,
  wayOpts    :: [String]
  }

way_details :: [ (WayName, Way) ]
way_details =
  [ (WayThreaded, Way "thr" True "Threaded" [
#if defined(freebsd_TARGET_OS)
411
412
413
414
415
416
417
--	  "-optc-pthread"
--      , "-optl-pthread"
	-- FreeBSD's default threading library is the KSE-based M:N libpthread,
	-- which GHC has some problems with.  It's currently not clear whether
	-- the problems are our fault or theirs, but it seems that using the
	-- alternative 1:1 threading library libthr works around it:
	  "-optl-lthr"
418
419
#elif defined(solaris2_TARGET_OS)
          "-optl-lrt"
420
421
422
423
424
425
426
427
#endif
	] ),

    (WayDebug, Way "debug" True "Debug" [] ),

    (WayProf, Way  "p" False "Profiling"
	[ "-fscc-profiling"
	, "-DPROFILING"
428
	, "-optc-DPROFILING" ]),
429

Simon Marlow's avatar
Simon Marlow committed
430
431
432
433
    (WayEventLog, Way  "l" True "RTS Event Logging"
	[ "-DEVENTLOG"
	, "-optc-DEVENTLOG" ]),

434
    (WayTicky, Way  "t" True "Ticky-ticky Profiling"  
435
	[ "-DTICKY_TICKY"
436
	, "-optc-DTICKY_TICKY" ]),
437
438
439
440
441
442
443
444
445
446

    -- optl's below to tell linker where to find the PVM library -- HWL
    (WayPar, Way  "mp" False "Parallel" 
	[ "-fparallel"
	, "-D__PARALLEL_HASKELL__"
	, "-optc-DPAR"
	, "-package concurrent"
        , "-optc-w"
        , "-optl-L${PVM_ROOT}/lib/${PVM_ARCH}"
        , "-optl-lpvm3"
447
        , "-optl-lgpvm3" ]),
448
449
450
451
452
453
454
455
456
457
458

    -- at the moment we only change the RTS and could share compiler and libs!
    (WayPar, Way  "mt" False "Parallel ticky profiling" 
	[ "-fparallel"
	, "-D__PARALLEL_HASKELL__"
	, "-optc-DPAR"
	, "-optc-DPAR_TICKY"
	, "-package concurrent"
        , "-optc-w"
        , "-optl-L${PVM_ROOT}/lib/${PVM_ARCH}"
        , "-optl-lpvm3"
459
        , "-optl-lgpvm3" ]),
460
461
462
463
464
465
466
467
468
469
470

    (WayPar, Way  "md" False "Distributed" 
	[ "-fparallel"
	, "-D__PARALLEL_HASKELL__"
	, "-D__DISTRIBUTED_HASKELL__"
	, "-optc-DPAR"
	, "-optc-DDIST"
	, "-package concurrent"
        , "-optc-w"
        , "-optl-L${PVM_ROOT}/lib/${PVM_ARCH}"
        , "-optl-lpvm3"
471
        , "-optl-lgpvm3" ]),
472
473
474
475
476

    (WayGran, Way  "mg" False "GranSim"
	[ "-fgransim"
	, "-D__GRANSIM__"
	, "-optc-DGRAN"
477
	, "-package concurrent" ]),
478
479

    (WayNDP, Way  "ndp" False "Nested data parallelism"
480
	[ "-XParr"
rl@cse.unsw.edu.au's avatar
rl@cse.unsw.edu.au committed
481
	, "-fvectorise"]),
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501

    (WayUser_a,  Way  "a"  False "User way 'a'"  ["$WAY_a_REAL_OPTS"]),	
    (WayUser_b,  Way  "b"  False "User way 'b'"  ["$WAY_b_REAL_OPTS"]),	
    (WayUser_c,  Way  "c"  False "User way 'c'"  ["$WAY_c_REAL_OPTS"]),	
    (WayUser_d,  Way  "d"  False "User way 'd'"  ["$WAY_d_REAL_OPTS"]),	
    (WayUser_e,  Way  "e"  False "User way 'e'"  ["$WAY_e_REAL_OPTS"]),	
    (WayUser_f,  Way  "f"  False "User way 'f'"  ["$WAY_f_REAL_OPTS"]),	
    (WayUser_g,  Way  "g"  False "User way 'g'"  ["$WAY_g_REAL_OPTS"]),	
    (WayUser_h,  Way  "h"  False "User way 'h'"  ["$WAY_h_REAL_OPTS"]),	
    (WayUser_i,  Way  "i"  False "User way 'i'"  ["$WAY_i_REAL_OPTS"]),	
    (WayUser_j,  Way  "j"  False "User way 'j'"  ["$WAY_j_REAL_OPTS"]),	
    (WayUser_k,  Way  "k"  False "User way 'k'"  ["$WAY_k_REAL_OPTS"]),	
    (WayUser_l,  Way  "l"  False "User way 'l'"  ["$WAY_l_REAL_OPTS"]),	
    (WayUser_m,  Way  "m"  False "User way 'm'"  ["$WAY_m_REAL_OPTS"]),	
    (WayUser_n,  Way  "n"  False "User way 'n'"  ["$WAY_n_REAL_OPTS"]),	
    (WayUser_o,  Way  "o"  False "User way 'o'"  ["$WAY_o_REAL_OPTS"]),	
    (WayUser_A,  Way  "A"  False "User way 'A'"  ["$WAY_A_REAL_OPTS"]),	
    (WayUser_B,  Way  "B"  False "User way 'B'"  ["$WAY_B_REAL_OPTS"]) 
  ]