Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

switch statement and numeric constants

58 views
Skip to first unread message

Klaus

unread,
May 27, 2005, 5:11:37 AM5/27/05
to
Hi all,

I want to the same thing in tcl as the following C code:

#define VAL_A 1
#define VAL_B 2
#define VAL_C 4

int x = VAL_A|VAL_C;

switch (x & (VAL_A|VAL_C)) {
case VAL_A: ... break;
case VAL_A|VAL_C: break;
}

the tcl code i tried was:
set VAL_A 1
set VAL_B 2
set VAL_C 4

switch -regexp expr( x & VAL_A|VAL_C) \
$VAL_A { } \
$VAL_C|$VAL_C {} \

but that did not work.

I think the usage on vars as const is wrong at first. But are there
named constants in tcl???
The second is that I could not avaluate expressions as case value...

Any hint?

Bye
Klaus

Donal K. Fellows

unread,
May 27, 2005, 6:20:55 AM5/27/05
to
Klaus wrote:
> switch -regexp expr( x & VAL_A|VAL_C) \
> $VAL_A { } \
> $VAL_C|$VAL_C {} \

You probably want something like this:

switch -exact -- [expr {$x & ($VAL_A|$VAL_C)}] \
$VAL_A { ... } \
[expr {$VAL_A|$VAL_C}] { ... }

The next level of thought is to disconnect from representing things as
integers in the first place and instead look at other representations
that take advantage of the fact that strings are *the* fundamental
datatype of Tcl (by contrast, in C it's really the machine-word). That's
quite a change though, and probably requires a lot of reworking of the
rest of your program too.

Donal.

Christopher Nelson

unread,
May 27, 2005, 8:28:39 AM5/27/05
to
Donal K. Fellows wrote:
> Klaus wrote:
> > switch -regexp expr( x & VAL_A|VAL_C) \
> > $VAL_A { } \
> > $VAL_C|$VAL_C {} \
>
> You probably want something like this:
>
> switch -exact -- [expr {$x & ($VAL_A|$VAL_C)}] \
> $VAL_A { ... } \
> [expr {$VAL_A|$VAL_C}] { ... }
>
> The next level of thought is to disconnect from representing things as
> integers in the first place and instead look at other representations
> that take advantage of the fact that strings are *the* fundamental
> datatype of Tcl (by contrast, in C it's really the machine-word).

Oh, I don't know. I think:

switch -- $something {
FOO {
}
BAR {
}
}

is fairly close to the C:

#define FOO 1
#define BAR 2

switch (something) {
case FOO:
break;
case BAR:
break;
}

I re-remembered this recently writing some Tcl to parse 802.1D BPDUs:

...
binary scan $bpdu "S c c c a*" \
a(protocol) a(rstpVersion) a(type) a(flags) bpdu

if {$a(protocol) != 0 } {
error "Invalid protocol"
}
switch -- $a(type) {
0 {
set a(type) "CFG"
}
0x80 {
set a(type) "TCN"
}
2 {
set a(type) "RST"
}
default {
error "Unknown BPDU type"
}
}
...

Then the rest of my code and use the fairly natural and expressive
strings.

Donal K. Fellows

unread,
May 27, 2005, 8:48:55 AM5/27/05
to
Christopher Nelson wrote:
> Oh, I don't know. I think:
> switch -- $something {
> FOO {
> }
> BAR {
> }
> }
> is fairly close to the C:

That'd be fine (even highly recommended), except he's switching on bit
patterns and not simple symbolic constants. That makes things much messier.

Donal.

Ralf Fassel

unread,
May 27, 2005, 9:21:55 AM5/27/05
to
* "Klaus" <lts-r...@gmx.de>

| the tcl code i tried was:
| set VAL_A 1
| set VAL_B 2
| set VAL_C 4
|
| switch -regexp expr( x & VAL_A|VAL_C) \
| $VAL_A { } \
| $VAL_C|$VAL_C {} \
|
| but that did not work.

What should that "$VAL_C|$VAL_C" mean?

Even the original


case VAL_A: ... break;
case VAL_A|VAL_C: break;

does not make much sense in that order (VAL_A will always trigger in
the first clause, the second will never run).

The "|" in C-case is best thought of as the
foo -
bar { }
in TCL-switch, so try
switch -- [expr {$x & ($VAL_A|$VAL_C)}] \
$VAL_A { puts VAL-A } \
SVAL_B - \
$VAL_C { puts "VAL-B (will never trigger) | VAL-C" }

Note: the precedence of & and | in TCl-expr are the same as in C, so
you need the same grouping in TCL-expr as in C-switch.

HTH
R'

Donal K. Fellows

unread,
May 27, 2005, 9:30:41 AM5/27/05
to
Ralf Fassel wrote:
> Even the original
> case VAL_A: ... break;
> case VAL_A|VAL_C: break;
> does not make much sense in that order (VAL_A will always trigger in
> the first clause, the second will never run).

Wrong. VAL_A|VAL_C is an expression with constant value 5, whereas VAL_A
on its own is an expression with constant value 1.

Donal.

Schelte Bron

unread,
May 27, 2005, 9:58:40 AM5/27/05
to
On 05/27/05 14:28, Christopher Nelson wrote:
> ...
> binary scan $bpdu "S c c c a*" \
> a(protocol) a(rstpVersion) a(type) a(flags) bpdu
>
> if {$a(protocol) != 0 } {
> error "Invalid protocol"
> }
> switch -- $a(type) {
> 0 {
> set a(type) "CFG"
> }
> 0x80 {
> set a(type) "TCN"
> }
> 2 {
> set a(type) "RST"
> }
> default {
> error "Unknown BPDU type"
> }
> }
> ...
>
You are aware that the switch command does string matching? This means
that the 0x80 pattern will never match the value of a variable that has
been set by binary scan c. Your pattern should probably be "-128".


Schelte.
--
set Reply-To [string map {nospam schelte} $header(From)]

Cameron Laird

unread,
May 27, 2005, 10:08:02 AM5/27/05
to
In article <1117196919.1...@z14g2000cwz.googlegroups.com>,
Christopher Nelson <cne...@nycap.rr.com> wrote:
.
.
.

> ...
> binary scan $bpdu "S c c c a*" \
> a(protocol) a(rstpVersion) a(type) a(flags) bpdu
>
> if {$a(protocol) != 0 } {
> error "Invalid protocol"
> }
> switch -- $a(type) {
> 0 {
> set a(type) "CFG"
> }
> 0x80 {
> set a(type) "TCN"
> }
> 2 {
> set a(type) "RST"
> }
> default {
> error "Unknown BPDU type"
> }
> }
> ...
>
>Then the rest of my code and use the fairly natural and expressive
>strings.
>

... and by the time you're writing *this*, it's often natural to
consider the alternative of

array set my_lookup_table {0 CFG
0x80 TCN
2 RST}
set a(type) $my_lookup_table($a(type))

along with a bit of exception-handling.

Also, as Donal notes, bit-pattern-ing can make things messier.

Klaus Rudolph

unread,
May 27, 2005, 11:51:34 AM5/27/05
to
Donal K. Fellows schrieb:

> Klaus wrote:
>
>> switch -regexp expr( x & VAL_A|VAL_C) \
>> $VAL_A { } \
>> $VAL_C|$VAL_C {} \
>
>
> You probably want something like this:
>
> switch -exact -- [expr {$x & ($VAL_A|$VAL_C)}] \
> $VAL_A { ... } \
> [expr {$VAL_A|$VAL_C}] { ... }
>


That is what I want!
Thanks a lot!

Klaus

0 new messages