dt_switch
Describes
recognized
switch. Kept as a data
record of type DT_SWITCH
at the base address of the switch (i.e. address of the command that
starts decoding of the switch variable).
typedef struct dt_switch { // Switch descriptor DT_SWITCH
ulong casemin; // Minimal case
ulong casemax; // Maximal case
ulong type; // Switch type, set of CASE_xxx
int nexit; // Number of exits including default
ulong exitaddr[NSWEXIT]; // List of exits (point to dt_case)
} dt_switch;
Members:
casemin
Minimal switch case
casemax
Maximal switch case. For signed switches, casemin, treated as an unsigned number, may be larger than casemax
type
Switch type, combination of the following constants:
CASE_CASCADED - switch is a cascaded IF, see note below
CASE_HUGE - either switch contains more than NSWEXIT exits, or some exit contains more than NSWCASE
cases, therefore switch decoding is incomplete
CASE_DEFAULT
- switch contains default case
CASE_ASCII -
most probably, switch cases correspond to ASCII characters
CASE_MSG -
most probably, switch cases can be interpreted as Windows messages WM_xxx
CASE_EXCPTN
- most probably, switch cases can be intrepreted as exception codes
(like 0xC0000005, ACCESSS_VIOLATION)
CASE_SIGNED
- if set, case values should be interpreted as signed numbers,
otherwise as unsigned
nexit
Number of
switch exits (not cases, see explanation below), including default. If number of exits exceeds NSWEXIT, analyser
limits nexit to
NSWEXIT and
sets flag CASE_HUGE in
type
exitaddr
List of
nexit switch exits. Each item contains address of exit described by the structure dt_case. Exits are not necessarily ordered
Note:
Analyser distinguishes between classical switches and cascaded IFs. Here is an example of the classical switch:
switch (i) {
case 0: do_something(); break;
case 1: do_anything(); break;
...
default: do_default();
}
In
this case, compiler creates highly effective sequence of the
commands that decode all mentioned values of i. Corresponding cascaded
IF
if (i==0)
do_something();
else if (i==1)
do_anything();
...
else
do_default();
has identical functionality, but compiler is forced to make all comparisons sequentially.
Note the difference between switch cases and switch exits. In the following example
switch (i) {
case 0:
case 1:
case 2:
do_something(); break;
case 3:
case 4:
case 5:
do_anything(); break;
default:
do_default();
}
there are 7 cases (0, 1, 2, 3, 4, 5, default) but only three switch exits (0,1,2; 3,4,5; default).
See
also: