[comp.lang.c] goto's and switch statements -- mild proposal

dhesi@bsu-cs.UUCP (Rahul Dhesi) (01/01/70)

In article <6289@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) 
writes (about "case 'a' :: 'z' :" and similar ranges in case statements):
      There's another serious problem underlying all these suggestions;
      namely, that "a through z" has a well-defined meaning [especially
      in an international setting].  The only well-defined ordering I
      think could be used meaningfully in a standard would have to be
      the native run-time collating sequence based on fixed-size letter
      units.

It seems simplest to me to stay with the character-is-integer paradigm
and treat each constant used to specify the range as an integer.  (I
note that K&R specifically say on page 202 that the 'constant-
expression' in a switch statement must be int.)  One thing I expect to
always be true for C, even as it evolves to accomodate different
character sets, is that each distinct character constant will
correspond to a distinct int value.  Otherwise a lot of code would
break badly, not to mention K&R's entire book.

Then the range is always well-defined, except that the compiler would
warn about empty ranges.  Also, the compiler would probably need to
warn about overlapping ranges.

Much of the time, when a range like this is used in a switch statement,
the user is thinking of a fast jump table implementation rather than an
if-then-else.  It's up to the user to make sure this makes sense, even
if the character set has holes.

Here's an aside not directed at anybody in particuler.

I think that for too long language designers have tried to accomodate
the vagaries of EBCDIC, specifically, that it's a character set with
holes.  Must every language accomodate every whim and fancy of every
badly-designed architecture?  The answer ought to be a resounding no.
The general principle is quite simple:  Those who choose to use
badly-designed machines should have to bear the burden of doing so
without dragging the rest of us down with them.

The six-character limit on external names (I hope it's gone from the
draft now) is another example of not applying this philosophy.  Why
does it make any sense for the rest of the world have to suffer from
the limitations of old linkers on old machines from the sixties?

We should certainly make an effort to accomodate all widely-used
architectures, but not at the expense of seriously distorting the
language for everybody else.
-- 
Rahul Dhesi         UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi

greg@utcsri.UUCP (01/01/70)

In article <6289@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <10265@orchid.waterloo.edu> rbutterworth@orchid.waterloo.edu (Ray Butterworth) writes:
>>    case 'a' :: 'z' :
>
>There's another serious problem underlying all these suggestions;
>namely, that "a through z" has a well-defined meaning.  Working
[...]
>in a general, i.e. international, environment.  Personally I
>think any assumption that there is a standard "dictionary order"
>based solely on "letter" sequencing for a given language is naive.
>
>Probably an application would be much better off using
>	if ( isalpha( c ) )
>		...
>or some other <ctype.h> function instead.  That is more likely to
>give the desired behavior outside the USASCII environment.

If you want it to run fast, and be portable:
	switch(char_class[c])[
		case IS_UPPER:	/*etc*/

...with char_class pre-stuffed using isupper, etc.
Or generate the entire switch automatically using another program.

-- 
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg
Have vAX, will hack...

hunt@spar.SPAR.SLB.COM (Neil Hunt) (01/01/70)

In article <869@tjalk.cs.vu.nl> rblieva@cs.vu.nl (Roemer B. Lievaart) writes:

>Oh yeah? How about the message I get for EVERY casted malloc or realloc:
>
>:: somefile.c(007): warning: possible pointer alignment problem
>
>Can't shut lint up about that.

I don't know which compiler you are using, but on the compiler I use,
this warning is avoided if you make sure that the compiler knows that
malloc returns a pointer by declaring it (char *). Even if you then
cast it into (something_else *), it accepts it, whereas if the compiler
thinks that [mc]alloc is (int), it will indeed issue this warning.

>BTW. Does anybody know how to stop lint complaining about functions
>returning values wich are always/sometimes ignored? I get one for every
>time I use sprintf, fclose, strcpy and quite a few others!
>[ OK, I meant another way than indeed using the values.
>  I just don't need them (always)! ]

Tell lint explicitly that you know that a value is returned, but you
are discarding it by calling the function with a (void) cast:

	char *sprintf();

	(void)sprintf(buffer, "%d", i);

Neil/.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/01/70)

In article <869@tjalk.cs.vu.nl> rblieva@cs.vu.nl (Roemer B. Lievaart) writes:
>BTW. Does anybody know how to stop lint complaining about functions
>returning values wich are always/sometimes ignored? I get one for every
>time I use sprintf, fclose, strcpy and quite a few others!

Traditionally, one just applies a (void) cast to the function result.
By the way, if you're not testing fclose() return value, you're risking
not detecting a write error.  fclose() can cause a write.

atbowler@orchid.UUCP (01/01/70)

In article <6289@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <10265@orchid.waterloo.edu> rbutterworth@orchid.waterloo.edu (Ray Butterworth) writes:
>>    case 'a' :: 'z' :
>
>There's another serious problem underlying all these suggestions;
>namely, that "a through z" has a well-defined meaning.  Working
>groups of /usr/group and/or IEEE P1003 are attempting to define
>what regular expressions (which include case ranges) would MEAN
>in a general, i.e. international, environment.  

I think you missed the point.  The request was for case ranges.
We all know that things can be misused, and the international alphabet
problem is a common one.  However, just because the original example
happened to pick an example that might or might not represent a problem
depending on the use of the program doesn't affect the original request.
    Ignore the fact that the example used character constants, and
think of them as integers.  e.g.
    case -9 :: -1:
    case  1 ::  9:

gnu@hoptoad.uucp (John Gilmore) (08/08/87)

rblieva@cs.vu.nl (Roemer b Lievaart) wrote:
> 	defolt:
> 	default:	/* code, probably error handler */
> 			break ;
> 	const1:		...
> 	const2:		if ( ! const2_allowed )
> 				goto defolt ;

I have had to use this kind of code too.  The goat ooze don't bother
me.  What bothers me is that I can't say:

				goto default;

and have it take me to the default: label.  While we're at it,
why not also allow "goto case XXX"?  Seems like this would make
state machines and such easier to read and write in C.
-- 
{dasys1,ncoast,well,sun,ihnp4}!hoptoad!gnu	     gnu@postgres.berkeley.edu
Alt.all: the alternative radio of the Usenet.

karl@haddock.ISC.COM (Karl Heuer) (08/10/87)

In article <2683@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
>What bothers me is that I can't say ["goto default" and "goto case N"].

It's interesting that this restriction exists, in view of the oft-stated claim
that the reason that switch statements have automatic fallthrough (rather than
automatic breakswitch) is that "case labels are just like real labels".

My own off-the-wall opinion is that "goto default" and "goto case N" should be
legal; non-switch labels should have to be declared (this allows one to reduce
the scope); label pointers should be allowed (with undefined effect if a goto
in one function references a label from another); it should be illegal to fall
into a label (one must instead write "goto foo; foo:"); and switch statements
should automatically break at the end of each case (thus freeing the keyword
"break" for loop exit exclusively).  Oh yes, this also requires a new notation
for multiple cases ("case '0'..'9':" or whatever).

These are just ideas, not a serious proposal.  Although they could be phased
in gradually, I do not expect any of them to happen in the forseeable future.
At best, some compilers/linters may introduce extensions/warnings for some of
my positive/negative points.

Flames are welcome, but please send them by e-mail.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

dant@tekla.TEK.COM (Dan Tilque;1893;92-789;LP=A;60HC) (08/11/87)

>John Gilmore writes:
>>What bothers me is that I can't say ["goto default" and "goto case N"].

Karl Heuer writes:
>It's interesting that this restriction exists, in view of the oft-stated claim
>that the reason that switch statements have automatic fallthrough (rather than
>automatic breakswitch) is that "case labels are just like real labels".

I would guess that the restriction is there to discourage the use of goto's.
I've never thought of cases as labels, but then I've never used a label in
C.  Cases certainly don't have the same syntax as labels.

>	it should be illegal to fall
>into a label (one must instead write "goto foo; foo:"); and switch statements
>should automatically break at the end of each case (thus freeing the keyword
>"break" for loop exit exclusively).  Oh yes, this also requires a new notation
>for multiple cases ("case '0'..'9':" or whatever).
>
I'd be hard put to come up with a better notation for:

	switch (c) {

	case CR:			/* assume appropriate #defines */
	case LF:
	case TAB:
	case ' ':
		/* whatever */
		.
		.
		.
These 4 values are not contiguous.  On possibility is to separating them
with commas:

	case CR, LF, TAB, ' ':

which changes the meaning of the comma operator.  Probably not a good idea.

However, I agree that it's bad programming to have this kind of thing:

	case 'a':
		a = b + count;
	case 'b':
		count += 2;
		.
		.
		.
Lint should definitely give warning since it's almost always the case that
what's desired is a break before case 'b':.  Also, one of my more frequent
mistakes is leaving breaks out of switches.


---
Dan Tilque
dant@tekla.tek.com  or dant@tekla.UUCP

edw@ius1.cs.cmu.edu (Eddie Wyatt) (08/11/87)

In article <916@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes:
> In article <2683@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
> >What bothers me is that I can't say ["goto default" and "goto case N"].
> 
> It's interesting that this restriction exists, in view of the oft-stated claim
> that the reason that switch statements have automatic fallthrough (rather than
> automatic breakswitch) is that "case labels are just like real labels".
> 
> Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint


   Consider the problems "goto case N" cause when there are two switch
statements each with a case N label in the function block.

   Also just consider how you would implement the two switch statements
each with a case N label.  Since each label is a posible target of 
a goto, it must be put into a label table for that function block.
Now you have  multiple defined labels (label N) unless you do a few
ugly things to uniquely define each label - but then look up on
labels become more expensive.

-- 

					Eddie Wyatt

e-mail: edw@ius1.cs.cmu.edu

edw@ius1.cs.cmu.edu (Eddie Wyatt) (08/11/87)

In article <2182@zeus.TEK.COM>, dant@tekla.TEK.COM (Dan Tilque;1893;92-789;LP=A;60HC) writes:
> However, I agree that it's bad programming to have this kind of thing:
> 
> 	case 'a':
> 		a = b + count;
> 	case 'b':
> 		count += 2;
> 		.
> 		.
> 		.
> Lint should definitely give warning since it's almost always the case that
> what's desired is a break before case 'b':.  Also, one of my more frequent
> mistakes is leaving breaks out of switches.

  Lexer I've written do things like that:


            case '+' :
            case '-' :
            case '0' :
            case '1' :
            case '2' :
            case '3' :
            case '4' :
            case '5' :
            case '6' :
            case '7' :
            case '8' :
            case '9' :
                while (isdigit(input()));
                if (*cc != '.')
                    {
                    (void) ungetc(*cc,yyin);
                    *cc = '\0';
                    return(TINTEGER);
                    }

            case '.' : /* float num */
                while (isdigit(input()));
		(void) ungetc(*cc,yyin);
                *cc = '\0';
                return(TREAL);
		break;
      
> 
> ---
> Dan Tilque
> dant@tekla.tek.com  or dant@tekla.UUCP

-- 

					Eddie Wyatt

e-mail: edw@ius1.cs.cmu.edu

ron@topaz.rutgers.edu.UUCP (08/11/87)

foo()  {

    switch(a) {
    default:
	dodefault();
    }

    goto default;

    switch(b)  {
    default:
	hithere();
    }
}

What happens here if you can "goto default" or "goto case"?

daveb@geac.UUCP (Brown) (08/12/87)

In article <1032@ius1.cs.cmu.edu> edw@ius1.cs.cmu.edu (Eddie Wyatt) writes:
>In article <916@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes:
>> In article <2683@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
>> >What bothers me is that I can't say ["goto default" and "goto case N"].
>> Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
>
>   Consider the problems "goto case N" cause when there are two switch
>statements each with a case N label in the function block.
>					Eddie Wyatt

  This is NOT a proposal for C (its for P, as in BCPL).
  One should restrict the range of gotos referring to switch/case/whatever
labels to the body of the switch, as in:

	...
	switch (foo) {
	case 'a':
		a(bar);		-- note no fall-through
	case 'f' | 'e':		-- one possible syntax...
		f(foo,bar);
		goto case 'a';	-- another possible syntax
	case DEL:
		goto crash;
	}
	...

	unwind();
	return bar;
 crash: 
	partially_unwind();
	return ERR;


  A "goto case x" outside a switch would be an error.

	--dave

	



-- 
 David Collier-Brown.                 |  Computer Science
 Geac Computers International Inc.,   |  loses its memory
 350 Steelcase Road,Markham, Ontario, |  (if not its mind)
 CANADA, L3R 1B3 (416) 475-0525 x3279 |  every 6 months.

karl@haddock.ISC.COM (Karl Heuer) (08/13/87)

In article <2182@zeus.TEK.COM> dant@tekla.UUCP (Dan Tilque) writes:
>[If switch statements had automatic break instead of fall-through, the
>current idiom "case CR: case LF: ..." wouldn't work.]  One possibility is
>separating them with commas: "case CR, LF, TAB, ' ':" which changes the
>meaning of the comma operator.  Probably not a good idea.

The comma operator is neither necessary nor useful in a constant expression,
and is explicitly disallowed by ANSI.

>However, I agree that it's bad programming to have this kind of thing:
>"case 'a':   a = b + count;   case 'b':   count += 2;".  Lint should
>definitely give warning since it's almost always the case that what's desired
>is a break before case 'b':.  Also, one of my more frequent mistakes is
>leaving breaks out of switches.

I agree, but (failing something stronger, such as my proposal) it should be
possible to turn off this warning, since some people intentionally write the
above.  A lintpragma /* FALLTHROUGH */ is the simplest solution.  I think some
implementations already have this.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

karl@haddock.ISC.COM (Karl Heuer) (08/13/87)

[Context: karl@haddock suggested that switch labels should behave more like
normal labels; and that the latter should have to be declared, giving them
block scope; and a bunch of related ideas.]

In article <1032@ius1.cs.cmu.edu> edw@ius1.cs.cmu.edu (Eddie Wyatt) writes:
>Consider the problems "goto case N" cause when there are two switch
>statements each with a case N label in the function block.

The solution is for the scope of a switch label to be the switch statement
itself.  Thus in the example posted in another article by ron@topaz, you get
an error message from the compiler.  If the switch statements are nested, you
get the innermost enclosing one.

>Also just consider how you would implement the two switch statements each
>with a case N label.  Since each label is a posible target of a goto, it must
>be put into a label table for that function block.  Now you have multiple
>defined labels (label N) unless you do a few ugly things to uniquely define
>each label - but then look up on labels become more expensive.

I don't see that this is any worse than the current situation with variables:
"{ int i; ... { double i; ... i=0; } }".  In fact, by removing the special
case (currently, labels are the only things that have function scope) it's
possible that this would simplify the compiler.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

edw@ius1.cs.cmu.edu (Eddie Wyatt) (08/13/87)

In article <930@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes:
> [Context: karl@haddock suggested that switch labels should behave more like
> normal labels; and that the latter should have to be declared, giving them
> block scope; and a bunch of related ideas.]
> 
> In article <1032@ius1.cs.cmu.edu> edw@ius1.cs.cmu.edu (Eddie Wyatt) writes:
> >Consider the problems "goto case N" cause when there are two switch
> >statements each with a case N label in the function block.
> 
> The solution is for the scope of a switch label to be the switch statement
> itself.  Thus in the example posted in another article by ron@topaz, you get
> an error message from the compiler.  If the switch statements are nested, you
> get the innermost enclosing one.
> 
> >Also just consider how you would implement the two switch statements each
> >with a case N label.  Since each label is a posible target of a goto, it must
> >be put into a label table for that function block.  Now you have multiple
> >defined labels (label N) unless you do a few ugly things to uniquely define
> >each label - but then look up on labels become more expensive.
> 
> I don't see that this is any worse than the current situation with variables:
> "{ int i; ... { double i; ... i=0; } }".  In fact, by removing the special
> case (currently, labels are the only things that have function scope) it's
> possible that this would simplify the compiler.
> 
  The problem I was describing here is the one where you have
two switch statements  not nested with case labels N.
If you where to support a label's scope extending over to the whole function
block then you have a different type of problem than the one you
have described above.  The scope of double i does not extend accross
the whole function, only the block that it is defined in, a much
simplier situation to deal with.

  If you where to restrict the scope of the label to the switch
statement which it is defined in then the problem of uniquely defining
the case label is analogous to uniquely defining nested variable
declarations.

  But if you only support a  label's scope over the switch statement
it is defined in then you have introduced a non-orthogonal feature into
the language since C label definitions extend over the whole function
block, not just the block they are defined in.

> Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

-- 

					Eddie Wyatt

e-mail: edw@ius1.cs.cmu.edu

rwa@auvax.UUCP (Ross Alexander) (08/13/87)

In article <1100@geac.UUCP>, daveb@geac.UUCP (Brown) writes:
>   This is NOT a proposal for C (its for P, as in BCPL).
>   One should restrict the range of gotos referring to switch/case/whatever
> labels to the body of the switch, as in:
> 	case 'f' | 'e':		-- one possible syntax...
> 		goto case 'a';	-- another possible syntax

A long time ago, when I was young and dinosaurs roamed the woods, I did
some hacking in a dialect of B called B+ (Reinhaldo de Braga, take a bow).
It supported a construct in case labels that we called 'a range case'.
it looked something like

	case 'a' - 'z' : <your code here>

and could be mixed with regular case labels and 'default' quite freely.
The impementation was very compact and efficient on the particular
architecture if the domain of cases wasn't too sparse, and the syntax
was very handy - I didn't want to enumerate the alphabet (yes, that
raises EBCDIC problems, but everything has gotcha's) in the example
above, and this way I didn't have to.

...!ihnp4!alberta!auvax!rwa	Ross Alexander @ Athabasca University

karl@haddock.ISC.COM (Karl Heuer) (08/13/87)

In article <1035@ius1.cs.cmu.edu> edw@ius1.cs.cmu.edu (Eddie Wyatt) writes:
|In article <930@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes:
|>[Context: karl@haddock suggested that switch labels should behave more like
|>normal labels; and that the latter should have to be declared, giving them
|>block scope; and a bunch of related ideas.]
|
|But if you only support a [case] label's scope over the switch statement
|it is defined in then you have introduced a non-orthogonal feature into
|the language since C label definitions extend over the whole function
|block, not just the block they are defined in.

Read my bits, Eddie.  Both my original suggestion and my followup (which you
quoted) explicitly said that normal labels ought to have block scope.  This
would *remove* a non-orthogonality in the language.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

molly@killer.UUCP (Molly Fredericks) (08/14/87)

In article <13874@topaz.rutgers.edu>, ron@topaz.rutgers.edu (Ron Natalie) writes:
> foo()  {
> 
>     switch(a) {
>     default:
> 	dodefault();
>     }
> 
>     goto default;
> 
>     switch(b)  {
>     default:
> 	hithere();
>     }
> }
> 
> What happens here if you can "goto default" or "goto case"?


$ ed test.c
main ()
{
	switch (getchar ()) {
		default:
			puts ("not a zero");
			break;
		case '0':
			puts ("was a zero");
			exit (0);
	}
	goto default;
}
$ cc -c test.c
"test.c", line 11: syntax error

That's what happens if you goto default.  The syntax for a goto is

	<goto_statement> ::= `goto' <identifier> `;'

The word `default' is not an identifier, it is a reserved word.

Molly
-- 
       Molly Fredericks       UUCP: { any place real }!ihnp4!killer!molly
    Disclaimer:  Neither me, nor my cat, had anything to do with any of this
  "I love giving my cat a bath, except for all those hairs I get on my tongue"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

molly@killer.UUCP (08/14/87)

In article <1032@ius1.cs.cmu.edu>, edw@ius1.cs.cmu.edu (Eddie Wyatt) writes:
> In article <916@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes:
> > In article <2683@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
> > >What bothers me is that I can't say ["goto default" and "goto case N"].
> 
>    Consider the problems "goto case N" cause when there are two switch
> statements each with a case N label in the function block.
> 
>    Also just consider how you would implement the two switch statements
> each with a case N label.  Since each label is a posible target of 
> a goto, it must be put into a label table for that function block.
> Now you have  multiple defined labels (label N) unless you do a few
> ugly things to uniquely define each label - but then look up on
> labels become more expensive.

The case statement labels already have to go into a label table to keep track
of what values have been entered so the default can be handled correctly.
Some compilers generate more than one type of code to handle a switch.  The
first variety of code is the

	cmpl	#value,d0
	beq	label

and the next is the word array (kinda maybe like ...)

	subl	#smallest,d0
	cmpl	#largest-smallest,d0
	bgt	default
	addl	d0,d0
	movw	6(pc,d0),d0
	jmp	2(pc,d0:w)

.word	label1
.word	labelN

and so on.  You can't discard the switch label info until the `}' that
closes the switch statement if you are generating code in this fashion.
(I invent a label that will appear after the last code from the switch
and jump there so I can defer the descision - I always hold onto my
switch tables)

The big bastard in this plan is the multiple labels.  You could add a
flag `Number of default: labels in this block' and allow goto default;
as a statement.  Or you might even allow it to be syntactically legal
inside of a switch.  Now that would be useful, except it's too easy
already.  But then, the goto case N is also easy -

	N = function to get value;
goto_case_N;
	switch (N) {
		.
		.
		.
	}

	N = some new value;
	goto goto_case_N;

Now that's an example of bogus code.

Molly

-- 
       Molly Fredericks       UUCP: { any place real }!ihnp4!killer!molly
    Disclaimer:  Neither me, nor my cat, had anything to do with any of this
  "I love giving my cat a bath, except for all those hairs I get on my tongue"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ron@topaz.rutgers.edu.UUCP (08/14/87)

I know that it doesn't compile now, how about paying attention to
the conversation before you post.  The proposal was to extend the
language to allow that feature, and I was pointing out an ambiguity
that goto labels don't have limitted scope but case labels do.

-Ron

peter@sugar.UUCP (Peter da Silva) (08/15/87)

Well... why not allow "goto case N" within the switch only?
-- 
-- Peter da Silva `-_-' ...!seismo!soma!uhnix1!sugar!peter (I said, NO PHOTOS!)

henry@utzoo.UUCP (Henry Spencer) (08/16/87)

> ... my original suggestion...
> explicitly said that normal labels ought to have block scope.  This
> would *remove* a non-orthogonality in the language.

Unfortunately, it would also break substantial amounts of existing code.
Vile, repellent, disgusting, but *currently legal* existing code.  That's
a no-no.
-- 
Support sustained spaceflight: fight |  Henry Spencer @ U of Toronto Zoology
the soi-disant "Planetary Society"!  | {allegra,ihnp4,decvax,utai}!utzoo!henry

rbutterworth@orchid.UUCP (08/17/87)

In article <298@auvax.UUCP>, rwa@auvax.UUCP (Ross Alexander) writes:
> A long time ago, when I was young and dinosaurs roamed the woods, I did
> some hacking in a dialect of B called B+ (Reinhaldo de Braga, take a bow).
> It supported a construct in case labels that we called 'a range case'.
> it looked something like
>     case 'a' - 'z' : <your code here>
> and could be mixed with regular case labels and 'default' quite freely.

The current version of B, now running on Honeywell GCOS-8 systems,
uses the syntax

    case 'a' :: 'z' :

This was suggested to the X3J11 people, but they rejected it
"on the grounds that a great deal of code (or jump table space)
might be generated for an innocent-looking case range such as
0 .. 65535 and that this was an unneeded innovation".

That this is an addition to the language and they don't have
a mandate to add new features I can accept.
The reasoning that someone might write a compiler stupidly enough
that it would use a jump table or 65535 explicit tests for the
given example doesn't make much sense to me though.

rblieva@cs.vu.nl (Roemer b Lievaart) (08/17/87)

In article <298@auvax.UUCP> rwa@auvax.UUCP (Ross Alexander) writes:
[...]
>
>A long time ago, when I was young and dinosaurs roamed the woods, I did
>some hacking in a dialect of B called B+ (Reinhaldo de Braga, take a bow).
>It supported a construct in case labels that we called 'a range case'.
>it looked something like
>
>	case 'a' - 'z' : <your code here>
>
[...]

Ah, yes! Don't we all get bored of typing:
case 'A': case 'B': case 'C':  .... etc until case 'Z':  ?

However, " case 'a' - 'z': " means ofcourse " case -25: " we probably had
better used something like '..' here (well, not *everything* in C should
be different from Pascal, should it? :-) )
I really would like to see the possibility to write " case 'A'..'Z': "
and probably also " case 'A'..'Z', 'a'..'z': ".  As already was pointed
out, the comma-operator is useless (and not allowed?) in constant
expressions, and the comma having two meanings already, who
cares for a third. All the other strange characters on my keyboard
that are not used (as operators) in C, don't seem to qualify for the
job. [ @`\# ]
Well, just an idea. It's just that I get sore fingers, sometimes.

				-- Roemer, Amsterdam, the Netherlands.
DISCLAIMER: we live in a democratic country!

gwyn@brl-smoke.ARPA (Doug Gwyn ) (08/18/87)

In article <10265@orchid.waterloo.edu> rbutterworth@orchid.waterloo.edu (Ray Butterworth) writes:
>    case 'a' :: 'z' :

There's another serious problem underlying all these suggestions;
namely, that "a through z" has a well-defined meaning.  Working
groups of /usr/group and/or IEEE P1003 are attempting to define
what regular expressions (which include case ranges) would MEAN
in a general, i.e. international, environment.  Personally I
think any assumption that there is a standard "dictionary order"
based solely on "letter" sequencing for a given language is naive.
The only well-defined ordering I think could be used meaningfully
in a standard would have to be the native run-time collating
sequence based on fixed-size letter units.  This would permit a
well-defined meaning to case ranges such as the above, IF the
native collating sequence is well-behaved (not EBCDIC, for
example, which has non-alphabetic characters within the numerical
range used for the English alphabet).

Probably an application would be much better off using
	if ( isalpha( c ) )
		...
or some other <ctype.h> function instead.  That is more likely to
give the desired behavior outside the USASCII environment.

rwa@auvax.UUCP (Ross Alexander) (08/19/87)

In article <6289@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> In article <10265@orchid.waterloo.edu> rbutterworth@orchid.waterloo.edu (Ray Butterworth) writes:
> >    case 'a' :: 'z' :
> 
> There's another serious problem underlying all these suggestions;
> namely, that "a through z" has a well-defined meaning.

Yes, and in my original article suggesting range cases as a possible extension
I pointed this problem out.  I view this as a problem with the environment
not the language.  For the sake of arguement, say I had a huge enum; I might
want to say

	case REDDISH_ORANGE :: SORT_OF_GREENISH :
		foo( bar );
		break;

Now where has your problem gone?  Since the enum is defined in the text,
the semantics of the range case are fully defined _in the text_, and we
are back to debating whether this is a good idea purely on it's own merits.
Or, to phrase it a bit differently, dragging character set (mis)
representations into the discussion is a bit of a red herring.

Remember, folks, I'm :-)'ing.  Flames to /dev/null, _content_ to the net.

...!ihnp4!alberta!auvax!rwa		Ross Alexander @ Athabasca University

karl@haddock.ISC.COM (Karl Heuer) (08/19/87)

In article <8414@utzoo.UUCP> henry@utzoo.UUCP (Henry Spencer) writes:
>[karl@haddock writes:]
>> ... my original suggestion... explicitly said that normal labels ought to
>> have block scope.  This would *remove* a non-orthogonality in the language.
>
>Unfortunately, it would also break substantial amounts of existing code.

As an intermediate step, declared labels could have block scope, while
undeclared labels would still have function scope.  Such an implementation
would be non-conforming, but only because the new keyword "label" invades the
user's namespace.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

mouse@mcgill-vision.UUCP (08/23/87)

In article <929@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes:
> In article <2182@zeus.TEK.COM> dant@tekla.UUCP (Dan Tilque) writes:
>> [switch statements with auto-break breaks "case foo: case bar: ...;"]
>> One possibility is separating them with commas: "case CR, LF:" which
>> changes the meaning of the comma operator.

> The comma operator is neither necessary nor useful in a constant
> expression, and is explicitly disallowed by ANSI.

Necessary?  True, since a constant expression by definition has no
side-effects.  Useful?  I disagree.  One of the prime uses of the comma
operator is for macros to expand into, and it can be nice (ie, clearer,
better style (whatever that means)) to be able to use a macro which
generates a comma expression, but whose result is constant with the
correct arguments, in a context like a switch case which requires a
constant expression.  (What a sentence.)  I don't see an example
immediately, but that's a poor excuse when I come up against a case
where I want one.  And it seems very against the UNIX philosophy, and
therefore the C philiosophy, to forbid something merely because it
seems useless at first glance.

>> However, I agree that it's bad programming to have [fall-through in
>> a switch, with statements between the case labels].  [...] it's
>> almost always the case that what's desired is a break before [the
>> second case].  Also, one of my more frequent mistakes is leaving
>> breaks out of switches.

Well, *I* don't have any trouble, because I have arranged my C-mode
such that Emacs won't dedent the case for me unless I have either a
break or a /* fall through */ there.

> I agree, but [...] it should be possible to turn off this warning,

I agree 155%.  Any warning should have a means to turn it off.  (For
most current warnings, which tend to be type clashes, this means is
provided: it's called a cast.)

					der Mouse

				(mouse@mcgill-vision.uucp)

peter@sugar.UUCP (Peter da Silva) (09/02/87)

>> 	case a, b, c:
>> Comma operator should be illegal in constant expressions.
> But I want to have my macros expand properly even if I use a constant.

That's exactly right. However, this isn't a problem any more
than the case of using a comma operator in an argument list.

i.e.
	foo(a,b,c);
and
	case a, b, c:
have the same problem if you
	#define a foo, bar
but... you should be doing
	#define a (foo, bar)
anyway, so where's the problem?
-- 
-- Peter da Silva `-_-' ...!seismo!soma!uhnix1!sugar!peter
--                  U   <--- not a copyrighted cartoon :->

rblieva@cs.vu.nl (Roemer b Lievaart) (09/02/87)

In article <867@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse) writes:
>
>I agree 155%.  Any warning should have a means to turn it off.  (For
>most current warnings, which tend to be type clashes, this means is
>provided: it's called a cast.)
>
Oh yeah? How about the message I get for EVERY casted malloc or realloc:

:: somefile.c(007): warning: possible pointer alignment problem

Can't shut lint up about that.

		--Roemer (pronounced "Rumo(u)r")

BTW. Does anybody know how to stop lint complaining about functions
returning values wich are always/sometimes ignored? I get one for every
time I use sprintf, fclose, strcpy and quite a few others!
[ OK, I meant another way than indeed using the values.
  I just don't need them (always)! ]

guy%gorodish@Sun.COM (Guy Harris) (09/03/87)

> Oh yeah? How about the message I get for EVERY casted malloc or realloc:
> 
> :: somefile.c(007): warning: possible pointer alignment problem
> 
> Can't shut lint up about that.

Don't use the "-p" or "-h" flag, and you won't get it, unless somebody's
monkeyed with that part of "lint".  Unfortunately, "-h" is quite useful for
other reasons.

Perhaps with the advent of ANSI C "lint" will be convinced not to complain
about converting "void *" to pointers of other types; there are both advantages
and disadvantages to this.

Another possibility would be to use "grep" to strip those messages out.

> BTW. Does anybody know how to stop lint complaining about functions
> returning values wich are always/sometimes ignored? I get one for every
> time I use sprintf, fclose, strcpy and quite a few others!
> [ OK, I meant another way than indeed using the values.
>   I just don't need them (always)! ]

If your compiler supports "void", try casting the result to "void", e.g.

	(void) strcpy(buffer, string);
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

chris@mimsy.UUCP (Chris Torek) (09/04/87)

In article <712@spar.SPAR.SLB.COM> hunt@spar.SPAR.SLB.COM (Neil Hunt) writes
[concerning `possible pointer alignment problem' warnings from lint
 on such code as `p = (int *)malloc(...);']:
>I don't know which compiler you are using, but on the compiler I use,
>this warning is avoided if you make sure that the compiler knows that
>malloc returns a pointer by declaring it (char *).

Try `lint -h'; plain `lint' does not complain under 4BSD, but -h is
useful for other things.  It might be reasonable to add an /*ALIGNOK*/
or /*ALIGNED*/ pragma; that seems to me better than making lint assume
that all `void *' functions return aligned pointers.

>>BTW. Does anybody know how to stop lint complaining about functions
>>returning values wich are always/sometimes ignored?

>Tell lint explicitly that you know that a value is returned, but you
>are discarding it by calling the function with a (void) cast:

Again, another pragma would be useful: /*DULLVALUE*/ could indicate
that the return value from a function need not be used.  strcpy and
strcat should be declared dull, but fclose should not, for it tells
whether an error occurred during closing.

>	char *sprintf();

Please do not declare sprintf `char *' if you can avoid it.  It will
soon be `int', if it is not already `int' on your machine.  For this
reason I put a declaration in my new <stdio.h>; it presently reads
`char *' but will presently read `int'.  (The double meaning of
presently is a moot :-) point, but not one we should discuss here.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

hunt@spar.SPAR.SLB.COM (Neil Hunt) (09/04/87)

In article <8394@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>In article <712@spar.SPAR.SLB.COM> hunt@spar.SPAR.SLB.COM (Neil Hunt) writes
>>	char *sprintf();
>
>Please do not declare sprintf `char *' if you can avoid it.  It will
>soon be `int', if it is not already `int' on your machine.

And what, pray, will be the value returned by such an integer sprintf ?
I suppose it will be the number of characters printed, or something else
equally useless. What about all my code where I do something like:

	f = fopen(sprintf(buf, filename, seq_num++), ...);

This seems like a gratuitous change to me !

Neil/.

guy%gorodish@Sun.COM (Guy Harris) (09/04/87)

> And what, pray, will be the value returned by such an integer sprintf ?
> I suppose it will be the number of characters printed, or something else
> equally useless.

I.e., as useless as its current return value?  It takes less effort to get the
address of the buffer than it does to get the length of the string; the latter
requires a call to "strlen" to get some information that, in many
implementations of "sprintf", is already at hand.

> What about all my code where I do something like:
> 
> 	f = fopen(sprintf(buf, filename, seq_num++), ...);

So change it to

	(void) sprintf(buf, filename, seq_num++);
	f = fopen(buf, ...);

What's the problem?  It may be trivially less "cute", but so what?

> This seems like a gratuitous change to me !

It may seem that way, but 1) it makes the "*printf" family more uniform to have
them all return the number of characters generated, 2) it causes "sprintf" to
return something that takes more effort to compute independently than does the
value it used to return, and 3) it's in the current ANSI C draft, so if you
don't like it you'd better make a last-ditch effort to get it changed or learn
to live with it.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

chris@mimsy.UUCP (Chris Torek) (09/04/87)

>In article <8394@mimsy.UUCP> I mentioned:
>>Please do not declare sprintf `char *' if you can avoid it.  It will
>>soon be `int', if it is not already `int' on your machine.

In article <732@spar.SPAR.SLB.COM> hunt@spar.SPAR.SLB.COM (Neil Hunt) writes:
>And what, pray, will be the value returned by such an integer sprintf ?
>I suppose it will be the number of characters printed,

Yes.

>or something else equally useless.

(Like its first argument?)

>What about all my code where I do something like:
>
>	f = fopen(sprintf(buf, filename, seq_num++), ...);

It has to become

	(void) sprintf(buf, filename, seq_num++);
	f = fopen(buf, ...);

>This seems like a gratuitous change to me !

Nonetheless, it is in the draft standard.  System V does it this
way, so someone is stuck with a change; it seems likely to be those
of us with `char *sprintf()'s.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@brl-smoke.UUCP (09/05/87)

In article <732@spar.SPAR.SLB.COM> hunt@spar.UUCP (Neil Hunt) writes:
>And what, pray, will be the value returned by such an integer sprintf ?
>I suppose it will be the number of characters printed, or something else
>equally useless.

Returning exactly the same argument you supplied is more useful than
telling you how much work the function did?

>What about all my code where I do something like:
>	f = fopen(sprintf(buf, filename, seq_num++), ...);

Already non-portable!

>This seems like a gratuitous change to me !

Change to what?  There are probably more int-returning *printf()s
out there than (char *)-returning ones.