From: ARNE@KOPC.HHS.DK (Arne Vajhxj)
Newsgroups: comp.os.vms
Subject: Re: problem report of toupper() in GCC 1.42 on VMS
Date: 24 Jan 93 16:14:55 GMT
Organization: The Internet

> GNU_CC_INCLUDE:[000000]ctype.h has the following utterly useless
> definition of toupper():
> 
>         #define toupper(c)      ((c)-'a'+'A')
> 
> since there exists a properly functioning routine in the RTL, the
> proper definition is:
> 
>         char toupper(char);
> 
> or, if you don't like the CALLS, roll yer own #define that makes
> (toupper('A') == toupper('a')) be a true value.
> 
> tolower() is similarly brain dead.

(this reply is rather long, but I think this problem deserves a proper
explanation)

It is correct, that the toupper and tolower in GNU C can give some horrible
problems !

The folowing program will work correct compiled with VAX C and will not
work correct with GNU C:

#include <string.h>
#include <ctype.h>
#include <stdio.h>

main()
{
   int i;
   char *s,ss[11];
   for (i=0;i<100000;i++) {
      strcpy(&ss,"abcdeABCDE");
      s = &ss;
      while (*s) {
         *s = toupper(*s);
         s++;
      };
   };
   printf("ss=%s\n",&ss);
};

With GNU C you will have to code as follows to have it work correct:

#include <string.h>
#include <ctype.h>
#include <stdio.h>

main()
{
   int i;
   char *s,ss[11];
   for (i=0;i<100000;i++) {
      strcpy(&ss,"abcdeABCDE");
      s = &ss;
      while (*s) {
         if (islower(*s)) *s = toupper(*s);
         s++;
      };
   };
   printf("ss=%s\n",&ss);
};

But please note, that even though the last piece of code looks more
complicated, then it is still faster !  The first program compiled
with VAX C 3.2 took 6.0 CPU seconds on a 4200 to run. The second
program compiled with GNU C 2.2.2 took only 1.5 CPU seocnds to run !

To help this VAX C's CTYPE.H defines a _toupper, which is purely inline:

#include <string.h>
#include <ctype.h>
#include <stdio.h>

main()
{
   int i;
   char *s,ss[11];
   for (i=0;i<100000;i++) {
      strcpy(&ss,"abcdeABCDE");
      s = &ss;
      while (*s) {
         *s = _toupper(*s);
         s++;
      };
   };
   printf("ss=%s\n",&ss);
};

This program compiled with VAX C 3.2 took only 2.5 seconds to run. [And
the difference between this number and the 1.5 number for the second GNU C
program is NOT due to anything regarding toupper, but comes from the fact
that VAX C translate strcpy to a callof strcpy, while GNU C translates strcpy
to a movc3 instruction].

Now we look at the header-files.

VAX C:

#define _toupper(c)	((c) >= 'a' && (c) <= 'z' ? (c) & 0x5F:(c))
int toupper(char c);

GNU C:

#define toupper(c)	((c)-'a'+'A')

"DECstation" C:

#ifdef __STDC__
int	_toupper( int __c );
int	toupper( int __c );
#else
extern	int	toupper();
#endif /* __STDC__ */

#if !defined(_POSIX_SOURCE) || defined(_XOPEN_SOURCE)
#define _toupper(c)	((c)-'a'+'A')
#endif

The last one looks a little weird to me !

What does the ANSI standard say about toupper ? [comments welcome]

This was a rather long post, but I think the problem is a little more
complex, than just saying "GNU C's toupper is bad and VAX C's toupper is
good" !

                                                          Arne

Arne Vajhxj                             local DECNET:  KO::ARNE
Computer Department                     PSI:           PSI%23831001304030::ARNE
Business School of Southern Denmark     Internet:      ARNE@KO.HHS.DK