StaticFlags.hs 14.9 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
31
32
33
34

	-- profiling opts
	opt_AutoSccsOnAllToplevs,
	opt_AutoSccsOnExportedToplevs,
	opt_AutoSccsOnIndividualCafs,
	opt_SccProfilingOn,
	opt_DoTickyProfiling,

andy@galois.com's avatar
andy@galois.com committed
35
36
37
        -- Hpc opts
	opt_Hpc,

38
39
40
41
42
43
	-- language opts
	opt_DictsStrict,
	opt_IrrefutableTuples,
	opt_Parallel,

	-- optimisation opts
44
        opt_PassCaseBndrToJoinPoints,
45
	opt_DsMultiTyVar,
46
	opt_NoStateHack,
47
        opt_SimpleListLiterals,
48
	opt_SpecInlineJoinPoints,
49
50
51
52
53
54
55
56
57
58
59
60
	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
61
62
63
	-- Optimization fuel controls
	opt_Fuel,

64
65
66
67
	-- Related to linking
	opt_PIC,
	opt_Static,

68
69
70
71
72
73
74
75
76
77
	-- misc opts
	opt_IgnoreDotGhci,
	opt_ErrorSpans,
	opt_GranMacros,
	opt_HiVersion,
	opt_HistorySize,
	opt_OmitBlackHoling,
	opt_Unregisterised,
	opt_EmitExternalCore,
	v_Ld_inputs,
78
	tablesNextToCode,
79
        opt_StubDeadValues,
80
81
82

    -- For the parser
    addOpt, removeOpt, addWay, findBuildTag, v_opt_C_ready
83
84
85
86
  ) where

#include "HsVersions.h"

87
import Config
88
import FastString
89
90
import Util
import Maybes		( firstJust )
91
import Panic
92

Simon Marlow's avatar
Simon Marlow committed
93
94
import Data.IORef
import System.IO.Unsafe	( unsafePerformIO )
95
import Data.List
96
97
98
99

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

100
101
initStaticOpts :: IO ()
initStaticOpts = writeIORef v_opt_C_ready True
102

Ian Lynagh's avatar
Ian Lynagh committed
103
addOpt :: String -> IO ()
104
105
addOpt = consIORef v_opt_C

Ian Lynagh's avatar
Ian Lynagh committed
106
addWay :: WayName -> IO ()
107
108
addWay = consIORef v_Ways

Ian Lynagh's avatar
Ian Lynagh committed
109
removeOpt :: String -> IO ()
110
111
112
113
114
115
116
117
118
119
120
121
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])
122
GLOBAL_VAR(v_opt_C_ready, False, Bool)
Ian Lynagh's avatar
Ian Lynagh committed
123
124

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

-- -static is the default
Ian Lynagh's avatar
Ian Lynagh committed
132
defaultStaticOpts :: [String]
133
134
defaultStaticOpts = ["-static"]

Ian Lynagh's avatar
Ian Lynagh committed
135
packed_static_opts :: [FastString]
136
137
138
139
140
141
142
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 
143
   = case firstJust (map (maybePrefixMatch sw) staticFlags) of
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
179
180
181
182
183
	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
184
opt_IgnoreDotGhci :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
185
opt_IgnoreDotGhci		= lookUp (fsLit "-ignore-dot-ghci")
186
187

-- debugging opts
Ian Lynagh's avatar
Ian Lynagh committed
188
opt_SuppressUniques :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
189
opt_SuppressUniques		= lookUp  (fsLit "-dsuppress-uniques")
dias@eecs.harvard.edu's avatar
dias@eecs.harvard.edu committed
190
opt_PprStyle_Debug  :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
191
opt_PprStyle_Debug		= lookUp  (fsLit "-dppr-debug")
dias@eecs.harvard.edu's avatar
dias@eecs.harvard.edu committed
192
opt_PprUserLength   :: Int
193
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
194
195
opt_Fuel            :: Int
opt_Fuel                        = lookup_def_int "-dopt-fuel" maxBound
Simon Marlow's avatar
Simon Marlow committed
196
197
198
opt_NoDebugOutput   :: Bool
opt_NoDebugOutput               = lookUp  (fsLit "-dno-debug-output")

199
200

-- profiling opts
Ian Lynagh's avatar
Ian Lynagh committed
201
opt_AutoSccsOnAllToplevs :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
202
opt_AutoSccsOnAllToplevs	= lookUp  (fsLit "-fauto-sccs-on-all-toplevs")
Ian Lynagh's avatar
Ian Lynagh committed
203
opt_AutoSccsOnExportedToplevs :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
204
opt_AutoSccsOnExportedToplevs	= lookUp  (fsLit "-fauto-sccs-on-exported-toplevs")
Ian Lynagh's avatar
Ian Lynagh committed
205
opt_AutoSccsOnIndividualCafs :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
206
opt_AutoSccsOnIndividualCafs	= lookUp  (fsLit "-fauto-sccs-on-individual-cafs")
Ian Lynagh's avatar
Ian Lynagh committed
207
opt_SccProfilingOn :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
208
opt_SccProfilingOn		= lookUp  (fsLit "-fscc-profiling")
Ian Lynagh's avatar
Ian Lynagh committed
209
opt_DoTickyProfiling :: Bool
210
opt_DoTickyProfiling            = WayTicky `elem` (unsafePerformIO $ readIORef v_Ways)
andy@galois.com's avatar
andy@galois.com committed
211

212
-- Hpc opts
Ian Lynagh's avatar
Ian Lynagh committed
213
opt_Hpc :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
214
opt_Hpc				= lookUp (fsLit "-fhpc")  
andy@galois.com's avatar
andy@galois.com committed
215

216
-- language opts
Ian Lynagh's avatar
Ian Lynagh committed
217
opt_DictsStrict :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
218
opt_DictsStrict			= lookUp  (fsLit "-fdicts-strict")
Ian Lynagh's avatar
Ian Lynagh committed
219
opt_IrrefutableTuples :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
220
opt_IrrefutableTuples		= lookUp  (fsLit "-firrefutable-tuples")
Ian Lynagh's avatar
Ian Lynagh committed
221
opt_Parallel :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
222
opt_Parallel			= lookUp  (fsLit "-fparallel")
223
224

-- optimisation opts
225
226
227
228
opt_DsMultiTyVar :: Bool
opt_DsMultiTyVar		= not (lookUp (fsLit "-fno-ds-multi-tyvar"))
	-- On by default

229
230
231
opt_PassCaseBndrToJoinPoints :: Bool
opt_PassCaseBndrToJoinPoints	= lookUp  (fsLit "-fpass-case-bndr-to-join-points")

Ian Lynagh's avatar
Ian Lynagh committed
232
opt_SpecInlineJoinPoints :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
233
opt_SpecInlineJoinPoints	= lookUp  (fsLit "-fspec-inline-join-points")
234

235
236
237
opt_SimpleListLiterals :: Bool
opt_SimpleListLiterals	        = lookUp  (fsLit "-fsimple-list-literals")

Ian Lynagh's avatar
Ian Lynagh committed
238
opt_NoStateHack :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
239
opt_NoStateHack			= lookUp  (fsLit "-fno-state-hack")
240

Ian Lynagh's avatar
Ian Lynagh committed
241
opt_CprOff :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
242
opt_CprOff			= lookUp  (fsLit "-fcpr-off")
243
	-- Switch off CPR analysis in the new demand analyser
Ian Lynagh's avatar
Ian Lynagh committed
244
opt_MaxWorkerArgs :: Int
245
246
opt_MaxWorkerArgs		= lookup_def_int "-fmax-worker-args" (10::Int)

Ian Lynagh's avatar
Ian Lynagh committed
247
opt_GranMacros :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
248
opt_GranMacros			= lookUp  (fsLit "-fgransim")
Ian Lynagh's avatar
Ian Lynagh committed
249
opt_HiVersion :: Integer
250
opt_HiVersion			= read (cProjectVersionInt ++ cProjectPatchLevel) :: Integer
Ian Lynagh's avatar
Ian Lynagh committed
251
opt_HistorySize :: Int
252
opt_HistorySize			= lookup_def_int "-fhistory-size" 20
Ian Lynagh's avatar
Ian Lynagh committed
253
opt_OmitBlackHoling :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
254
opt_OmitBlackHoling		= lookUp  (fsLit "-dno-black-holing")
255
256
opt_StubDeadValues  :: Bool
opt_StubDeadValues		= lookUp  (fsLit "-dstub-dead-values")
257
258

-- Simplifier switches
Ian Lynagh's avatar
Ian Lynagh committed
259
opt_SimplNoPreInlining :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
260
opt_SimplNoPreInlining		= lookUp  (fsLit "-fno-pre-inlining")
261
262
	-- NoPreInlining is there just to see how bad things
	-- get if you don't do it!
Ian Lynagh's avatar
Ian Lynagh committed
263
opt_SimplExcessPrecision :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
264
opt_SimplExcessPrecision	= lookUp  (fsLit "-fexcess-precision")
265
266

-- Unfolding control
Ian Lynagh's avatar
Ian Lynagh committed
267
opt_UF_CreationThreshold :: Int
268
opt_UF_CreationThreshold	= lookup_def_int "-funfolding-creation-threshold"  (45::Int)
Ian Lynagh's avatar
Ian Lynagh committed
269
opt_UF_UseThreshold :: Int
270
opt_UF_UseThreshold		= lookup_def_int "-funfolding-use-threshold"	   (8::Int)	-- Discounts can be big
Ian Lynagh's avatar
Ian Lynagh committed
271
opt_UF_FunAppDiscount :: Int
272
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
273
opt_UF_KeenessFactor :: Float
274
275
opt_UF_KeenessFactor		= lookup_def_float "-funfolding-keeness-factor"	   (1.5::Float)

Ian Lynagh's avatar
Ian Lynagh committed
276
opt_UF_DearOp :: Int
277
opt_UF_DearOp   = ( 4 :: Int)
Ian Lynagh's avatar
Ian Lynagh committed
278

dias@eecs.harvard.edu's avatar
dias@eecs.harvard.edu committed
279
280

-- Related to linking
Ian Lynagh's avatar
Ian Lynagh committed
281
opt_PIC :: Bool
282
283
284
#if darwin_TARGET_OS && x86_64_TARGET_ARCH
opt_PIC                         = True
#else
Ian Lynagh's avatar
Ian Lynagh committed
285
opt_PIC                         = lookUp (fsLit "-fPIC")
286
#endif
Ian Lynagh's avatar
Ian Lynagh committed
287
opt_Static :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
288
opt_Static			= lookUp  (fsLit "-static")
Ian Lynagh's avatar
Ian Lynagh committed
289
opt_Unregisterised :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
290
opt_Unregisterised		= lookUp  (fsLit "-funregisterised")
291
292
293
294
295

-- 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
296
tablesNextToCode :: Bool
297
298
299
tablesNextToCode 		= not opt_Unregisterised
		 		  && cGhcEnableTablesNextToCode == "YES"

Ian Lynagh's avatar
Ian Lynagh committed
300
opt_EmitExternalCore :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
301
opt_EmitExternalCore		= lookUp  (fsLit "-fext-core")
302
303

-- Include full span info in error messages, instead of just the start position.
Ian Lynagh's avatar
Ian Lynagh committed
304
opt_ErrorSpans :: Bool
Ian Lynagh's avatar
Ian Lynagh committed
305
opt_ErrorSpans			= lookUp (fsLit "-ferror-spans")
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
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
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363


-- 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
  | 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
364
allowed_combination :: [WayName] -> Bool
365
366
367
368
369
370
371
372
373
374
375
376
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
377
	WayThreaded `allowedWith` WayProf	= True
378
379
380
381
382
383
	_ `allowedWith` _ 			= False


findBuildTag :: IO [String]  -- new options
findBuildTag = do
  way_names <- readIORef v_Ways
384
  let ws = sort (nub way_names)
385
386

  if not (allowed_combination ws)
387
      then ghcError (CmdLineError $
388
389
390
391
392
393
394
395
396
397
398
399
      		    "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)

400
401


402
403
404
mkBuildTag :: [Way] -> String
mkBuildTag ways = concat (intersperse "_" (map wayTag ways))

Ian Lynagh's avatar
Ian Lynagh committed
405
lkupWay :: WayName -> Way
406
407
408
409
410
lkupWay w = 
   case lookup w way_details of
	Nothing -> error "findBuildTag"
	Just details -> details

Ian Lynagh's avatar
Ian Lynagh committed
411
isRTSWay :: WayName -> Bool
412
413
isRTSWay = wayRTSOnly . lkupWay 

414
415
416
417
418
419
420
421
422
423
424
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)
425
426
427
428
429
430
431
--	  "-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"
432
433
#elif defined(solaris2_TARGET_OS)
          "-optl-lrt"
434
435
436
437
438
439
440
441
#endif
	] ),

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

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

444
    (WayTicky, Way  "t" True "Ticky-ticky Profiling"  
445
	[ "-DTICKY_TICKY"
446
	, "-optc-DTICKY_TICKY" ]),
447
448
449
450
451
452
453
454
455
456

    -- 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"
457
        , "-optl-lgpvm3" ]),
458
459
460
461
462
463
464
465
466
467
468

    -- 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"
469
        , "-optl-lgpvm3" ]),
470
471
472
473
474
475
476
477
478
479
480

    (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"
481
        , "-optl-lgpvm3" ]),
482
483
484
485
486

    (WayGran, Way  "mg" False "GranSim"
	[ "-fgransim"
	, "-D__GRANSIM__"
	, "-optc-DGRAN"
487
	, "-package concurrent" ]),
488
489

    (WayNDP, Way  "ndp" False "Nested data parallelism"
490
	[ "-XParr"
rl@cse.unsw.edu.au's avatar
rl@cse.unsw.edu.au committed
491
	, "-fvectorise"]),
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511

    (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"]) 
  ]