[net.lang.c] Switch case common code

ruff@cisden.UUCP (06/06/86)

This problem was floating around a while ago, but I thought this might be
an interesting revisitation.  Given the following bit of code:

	switch (switch_variable) {
	case a:
		...
		...
		common_code_for_a_and_b
		break;

	case b:
		...
		...
		common_code_for_a_and_b
		break;

	case c:
		...
		...
		break;
	}

The problem was to write (for whatever reason) the common_code_for_a_and_b
exactly once in the source, and not as a function.  Since the definition
of the language does not require a compound statement after the switch,
you could write it in several hideous ways...

	switch (switch_variable)
		for (; FALSE; common_code_for_a_and_b) {
			case a:
				...
				...
				continue;

			case b:
				...
				...
				continue;

			case c:
				...
				...
				break;
		}

or

	switch (switch_variable) {
		while (TRUE) {
			case a:
				...
				...
				break; /* From while only! */

			case b:
				...
				...
				break; /* From while only! */
		}
		common_code_for_a_and_b;
		break; /* From switch! */

		case c:
			...
			...
			break; /* From switch! */
	}

Of course, there are some restrictions on the type of statements in
the for statement, but you could implement ifs and other types with
the setjmp/longjmp facility as in that prime finding program that
showed up on the net some time ago...

Yes, I know that you really shouldn't do anything this way, but
it was fun!  There is no restriction on where the case labels reside
within the scope of the switch statement.  Of course, with an auxillary
variable and the for, you could implement the common_code_comes_first variation.

	flag = FALSE;
	switch (switch_variable)
		for (; TRUE; common_code_for_a_and_b, flag = TRUE) {
			case a:
				if (flag == FALSE)
					continue;
				if (switch_variable != a) {
					...
					...
					break;
				}

			case b:
				if (flag == FALSE)
					continue;
				if (switch_variable != b) {
					...
					...
					break;
				}

			break; /* To separate from non-common code cases */

			case c:
				...
				...
				break;
		}
		
These constructs would be excellent candidates for the obfuscated C contest.

					Craig Ruff
					hao!cisden!ruff

lvc@danews.UUCP (Larry Cipriani) (06/10/86)

The 'best' I think that can be done is to do something like:

	switch (switch_variable)
	{
	case a: ...
		...
		goto common;
		break;

	case b: ...
		...
	common:	common_code_for_a_and_b
		break;

	case c: ...
		...
		break;
	}

Gotos are usually abused, but I think the for/while stuff shown
is just awful.  I think this is a lot easier to understand.  No ?
-- 

Larry Cipriani		AT&T Network Systems
danews!lvc		"Nothing is worse than an itch you can never scratch."

pmg@aplvax.UUCP (P. Michael Guba) (06/11/86)

Maybe I missed some restrictions someone put
on how this problem can be solved. 
If not, I suggest putting the common code into
a function.  This seems to be the cleanest solution
and it provides a lot more flexibility.

	switch(char) {
	case 'a':
		. . .
		common_code();
	case 'b':
		common_code();
		. . .
	case 'c':
		. . .
	}
-- 
P. Michael Guba			...seismo!umcp-cs!aplvax!pmg
JHU/Applied Physics Lab
Johns Hopkins Road
Laurel, Maryland 20707		(301) 953-6829

jay@isis.UUCP (Jay Batson) (06/11/86)

In article <134@danews.UUCP> lvc@danews.UUCP (Larry Cipriani) writes:
>The 'best' I think that can be done is to do something like:
>	switch (switch_variable)
>	{
>	case a: ...
>		goto common;
>		break;
>	case b: ...
>	common:	common_code_for_a_and_b
>		break;
>	case c: ...
>		break;
>	}
>Gotos are usually abused, but I think the for/while stuff shown
>is just awful.  I think this is a lot easier to understand.  No ?

Yes.  Craig, you're bright, and you've helped me lots before.  But I
agree with Larry for _this_ question.  But, Craig's article _was_
an interesting posting, I'm sure all will agree.
--------

"OK, so now, after it gets dark Lancelot and I will jump out of the rabbit, and
 take the castle by supr........ oh."

Jay Batson
{seismo,hplabs}!hao!isis!jay

mkr@mmm.UUCP (MKR) (06/19/86)

In article <134@danews.UUCP> lvc@danews.UUCP (Larry Cipriani) writes:
>The 'best' I think that can be done is to do something like:
>
>	switch (switch_variable)
>	{
>	case a: ...
>		...
>		goto common;
>		break;
>
>	case b: ...
>		...
>	common:	common_code_for_a_and_b
>		break;
>
>	case c: ...
>		...
>		break;
>	}
>
>Larry Cipriani		AT&T Network Systems

	Why not:

int common_stuff()
{
	blahblahblah
}

main()
{
...
	switch (thnad) {
	case A:
		do the A stuff;
		common_stuff();
		break;
	case B:
		do the B stuff;
		common_stuff();
		break;
	case C:
		do the C stuff;
		break;
	}

I thought that's what functions were for.

	--MKR

lvc@danews.UUCP (Larry Cipriani) (06/24/86)

> int common_stuff()
> {
> 	blahblahblah
> }
> 
> main()
> {
> ...
> 	switch (thnad) {
> 	case A:
> 		do the A stuff;
> 		common_stuff();
> 		break;
> 	case B:
> 		do the B stuff;
> 		common_stuff();
> 		break;
> 	case C:
> 		do the C stuff;
> 		break;
> 	}
> 
> I thought that's what functions were for.
> 
> 	--MKR

One of the requirements of the original request is that
a function not be used.

A reason not to use a function is that the scoping rules
get in the way, and force one to either use lots of global
varibles (yuck) or pass the function addresses of variables
and manipulate them through indirection (still yucky).

Another is that in a realtime process you might want to keep
the number of function calls to a minimum.
-- 

Larry Cipriani		AT&T Network Systems
danews!lvc		"Nothing is worse than an itch you can never scratch."