This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Problem with using <ctype.h> with gcc 3.0.3 on SCO 5.0.5


I present below a sample program to demonstrate the problem. It consists of
a shared library and an executable.

The contents of the shared library are :

/* file : mylib.cpp */
#include <ctype.h>

int foo(unsigned char c)
{
//  if (isalnum(c)); /* Error */
//  if (isalpha(c)); /* No Error */
//  if (iscntrl(c)); /* Error */
//  if (isdigit(c)); /* Error */
//  if (isgraph(c)); /* No Error */
//  if (islower(c)); /* Error */
//  if (isprint(c)); /* No Error */
//  if (ispunct(c)); /* Error */
  if (isspace(c)); /* Error */
//  if (isupper(c)); /* Error */
//  if (isxdigit(c)); /* Error */
//  if (tolower(c)); /* No Error */
//  if (toupper(c)); /* No Error */
//  if (isascii(c)); /* No Error */
//  if (toascii(c)); /* No Error */
//  if (__tolower(c)); /* No Error */
//  if (__toupper(c)); /* No Error */
//  if (__todigit(c)); /* No Error */
//  if (__toint(c)); /* No Error */
//  if (todigit(c)); /* No Error */
//  if (toint(c)); /* No Error */
//  if (_toupper(c)); /* No Error */
//  if (_tolower(c)); /* No Error */

  return 0;
}

The contents of the executable are :

#include <iostream>

int main()
{
  int num1, num2;

  std::cout << "Enter number 1 ->> ";
  std::cin >> num1;

  std::cout << std::endl << "Enter number 2 ->> ";
  std::cin >> num2;

  std::cout << std::endl << num1 << " + " << num2 << " = " << num1 + num2 <<
std::endl;

  return 0;
}

I do the following :

$ g++ -c mylib.cpp
$ g++ -G mylib.o -o libmylib.so
$ g++ -c mytest.cpp
$ g++ mytest.o -L. -lmylib -o mytest

$ ./mytest
Enter number 1 ->> 12

Enter number 2 ->>
-2147398527 + -2147110048 = 4587211535

I have indicated in the source for the shared library above the *functions*
(actually these are macros in the header <ctype.h>) that cause this error.
The prolem is that "cin" refuses to behave properly if any of these is used
in a shared library and that library is linked to the executable
(irrespective of 
whether the function in which they were used is subsequently used in the
executable or not).

This behaviour is not visible if I include the function in the shared
library directly into the source file, i.e. if I do not use a shared
library.

One common thing about the *functions* that cause this error is that they
all use an array named "__ctype[]" declared as *extern* in header <ctype.h>.
This array is the reason for the problem since if I change it to and
alternative array "__ctype2[]" declared in the same header, the error goes
away. I agree the results will not be correct but it atleast establishes
that the problem is with this array.

The preprocessor output for the file mylib.cpp is given below.

# 1 "mylib.cpp"
# 1 "/usr/include/ctype.h" 1 3
# 41 "/usr/include/ctype.h" 3
#pragma comment(exestr, "xpg4plus @(#) ctype.h 20.2 95/02/10 ")


extern "C" {
# 99 "/usr/include/ctype.h" 3
extern int (isalnum)(int);
extern int (isalpha)(int);
extern int (iscntrl)(int);
extern int (isdigit)(int);
extern int (isgraph)(int);
extern int (islower)(int);
extern int (isprint)(int);
extern int (ispunct)(int);
extern int (isspace)(int);
extern int (isupper)(int);
extern int (isxdigit)(int);
extern int tolower(int);
extern int toupper(int);

extern int isascii(int);
extern int toascii(int);
extern int __tolower(int);
extern int __toupper(int);

extern unsigned char __ctype[];


extern unsigned char __ctype2[];





inline int __inlineisalpha(int __c) { return((__c == (-1) ?
                          (__ctype2 + 1)[__c] :
                          (__ctype2 + 1)[(unsigned char)__c]) & 0001); }

inline int __inlineisupper(int __c) { return((__c == (-1) ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)__c]) & 01); }

inline int __inlineislower(int __c) { return((__c == (-1) ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)__c]) & 02); }

inline int __inlineisdigit(int __c) { return((__c == (-1) ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)__c]) & 04); }

inline int __inlineisxdigit(int __c) { return((__c == (-1) ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)__c]) & 0200); }

inline int __inlineisspace(int __c) { return((__c == (-1) ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)(__c)]) & 010); }

inline int __inlineispunct(int __c) { return((__c == (-1) ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)(__c)]) & 020); }

inline int __inlineisprint(int __c) { return((__c == (-1) ?
                          (__ctype2 + 1)[__c] :
                          (__ctype2 + 1)[(unsigned char)(__c)]) & 0004); }

inline int __inlineisgraph(int __c) { return((__c == (-1) ?
                          (__ctype2 + 1)[__c] :
                          (__ctype2 + 1)[(unsigned char)(__c)]) & 0002); }

inline int __inlineiscntrl(int __c) { return((__c == (-1) ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)(__c)]) & 040); }

inline int __inlineisalnum(int __c) { return(__c == (-1) ?
                          (((__ctype + 1)[__c] & (01 | 02 | 04)) ||
                           ((__ctype2 + 1)[__c] & 0001)) :
                          (((__ctype + 1)[(unsigned char)__c] & (01 | 02 |
04)) ||
                           ((__ctype2 + 1)[(unsigned char)__c] & 0001)))
; }
# 223 "/usr/include/ctype.h" 3
}
# 2 "mylib.cpp" 2

int foo(unsigned char c)
{
# 13 "mylib.cpp"
  if (__inlineisspace(c));
# 29 "mylib.cpp"
  return 0;
}


I provide below the header <ctype.h> from a SCO Openserver 5.0.5 system that
has gcc 3.0.3 installed.

/* Copyright 1994-1995 The Santa Cruz Operation, Inc. All Rights Reserved.
*/


#if defined(_NO_PROTOTYPE)      /* Old, crufty environment */
#include <oldstyle/ctype.h>
#elif defined(_XOPEN_SOURCE_EXTENDED)   /* Xpg4v2 environment */
#include <xpg4v2/ctype.h>
#elif defined(_XOPEN_SOURCE) || defined(_XPG4_VERS)     /* Xpg4 environment
*/
#include <xpg4/ctype.h>
#elif defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) /* Posix
environment */
#include <posix/ctype.h>
#elif _STRICT_ANSI      /* Pure Ansi/ISO environment */
#include <ansi/ctype.h>
#elif defined(_SCO_ODS_30) /* Old, Tbird compatible environment */
#include <ods_30_compat/ctype.h>
#else   /* Normal, default environment */
/*
 *   Portions Copyright (C) 1983-1995 The Santa Cruz Operation, Inc.
 *              All Rights Reserved.
 *
 *      The information in this file is provided for the exclusive use of
 *      the licensees of The Santa Cruz Operation, Inc.  Such users have the
 *      right to use, modify, and incorporate this code into other products
 *      for purposes authorized by the license agreement provided they
include
 *      this notice and the associated copyright notice with any such
product.
 *      The information in this file is provided "AS IS" without warranty.
 */

/*      Portions Copyright (c) 1990, 1991, 1992, 1993 UNIX System
Laboratories, Inc. */
/*      Portions Copyright (c) 1979 - 1990 AT&T   */
/*        All Rights Reserved   */

/*      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF          */
/*      UNIX System Laboratories, Inc.                          */
/*      The copyright notice above does not evidence any        */
/*      actual or intended publication of such source code.     */

#ifndef _CTYPE_H
#define _CTYPE_H

#pragma comment(exestr, "xpg4plus @(#) ctype.h 20.2 95/02/10 ")

#ifdef __cplusplus
extern "C" {
#endif

#ifndef _U
#define _U      01      /* Upper case  */
#define _L      02      /* Lower case  */
#define _N      04      /* Numeral (digit)  */
#define _S      010     /* Spacing character  */
#define _P      020     /* Punctuation  */
#define _C      040     /* Control character  */
#define _B      0100    /* Blank  */
#define _X      0200    /* heXadecimal digit  */
#endif
#ifndef _A
/*
 * New character classes for XPG4 to be used with __ctype2[].
 */
#define _A 0001         /* Alpha Character */
#define _G 0002         /* Graphic Character */
#define _R 0004         /* Print Character */
#endif

/* Very ascii dependent */

#define __todigit(n)   ((char)((n)+'0'))
#define __toint(c)     ((int)((c)-'0'))

#define todigit(n)   ((char)((n)+'0'))
#define toint(c)     ((int)((c)-'0'))

#ifdef __cplusplus
/* Necessary so (islanum) yields "right" function in library */
#define isalnum(x) __inlineisalnum(x)
#define isalpha(x) __inlineisalpha(x)
#define iscntrl(x) __inlineiscntrl(x)
#define isdigit(x) __inlineisdigit(x)
#define isgraph(x) __inlineisgraph(x)
#define islower(x) __inlineislower(x)
#define isprint(x) __inlineisprint(x)
#define ispunct(x) __inlineispunct(x)
#define isspace(x) __inlineisspace(x)
#define isupper(x) __inlineisupper(x)
#define isxdigit(x) __inlineisxdigit(x)
#else
/* Use inline function in C++ */
static int __c; /* necessary to ensure param evaluated once */
#endif

#ifdef EOF
#define _EOF_ EOF
#else
#define _EOF_ (-1)
#endif


extern int      (isalnum)(int);
extern int      (isalpha)(int);
extern int      (iscntrl)(int);
extern int      (isdigit)(int);
extern int      (isgraph)(int);
extern int      (islower)(int);
extern int      (isprint)(int);
extern int      (ispunct)(int);
extern int      (isspace)(int);
extern int      (isupper)(int);
extern int      (isxdigit)(int);
extern int      tolower(int);
extern int      toupper(int);

extern int      isascii(int);
extern int      toascii(int);
extern int      __tolower(int);
extern int      __toupper(int);

extern unsigned char    __ctype[];


extern unsigned char    __ctype2[];

#if !defined(__lint)
#ifdef __cplusplus

inline int __inlineisalpha(int __c) {   return((__c == _EOF_ ?
                          (__ctype2 + 1)[__c] :
                          (__ctype2 + 1)[(unsigned char)__c]) & _A); }

inline int __inlineisupper(int __c) {   return((__c == _EOF_ ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)__c]) & _U); }

inline int __inlineislower(int __c) {   return((__c == _EOF_ ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)__c]) & _L); }

inline int __inlineisdigit(int __c) {   return((__c == _EOF_ ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)__c]) & _N); }

inline int __inlineisxdigit(int __c) {  return((__c == _EOF_ ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)__c]) & _X); }

inline int __inlineisspace(int __c) {   return((__c == _EOF_ ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)(__c)]) & _S); }

inline int __inlineispunct(int __c) {   return((__c == _EOF_ ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)(__c)]) & _P); }

inline int __inlineisprint(int __c) {   return((__c == _EOF_ ?
                          (__ctype2 + 1)[__c] :
                          (__ctype2 + 1)[(unsigned char)(__c)]) & _R); }

inline int __inlineisgraph(int __c) {   return((__c == _EOF_ ?
                          (__ctype2 + 1)[__c] :
                          (__ctype2 + 1)[(unsigned char)(__c)]) & _G); }

inline int __inlineiscntrl(int __c) {   return((__c == _EOF_ ?
                          (__ctype + 1)[__c] :
                          (__ctype + 1)[(unsigned char)(__c)]) & _C); }

inline int __inlineisalnum(int __c) {   return(__c == _EOF_ ?
                          (((__ctype + 1)[__c] & (_U | _L | _N)) ||
                           ((__ctype2 + 1)[__c] & _A)) :
                          (((__ctype + 1)[(unsigned char)__c] & (_U | _L |
_N)) ||
                           ((__ctype2 + 1)[(unsigned char)__c] & _A)))
; }


#else
#define isalpha(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype2 + 1)[__c] : \
                          (__ctype2 + 1)[(unsigned char)__c]) & _A)
#define isupper(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype + 1)[__c] : \
                          (__ctype + 1)[(unsigned char)__c]) & _U)
#define islower(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype + 1)[__c] : \
                          (__ctype + 1)[(unsigned char)__c]) & _L)
#define isdigit(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype + 1)[__c] : \
                          (__ctype + 1)[(unsigned char)__c]) & _N)
#define isxdigit(c)     (((__c = (c)) == _EOF_ ? \
                          (__ctype + 1)[__c] : \
                          (__ctype + 1)[(unsigned char)__c]) & _X)
#define isspace(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype + 1)[__c] : \
                          (__ctype + 1)[(unsigned char)(__c)]) & _S)
#define ispunct(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype + 1)[__c] : \
                          (__ctype + 1)[(unsigned char)(__c)]) & _P)
#define isprint(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype2 + 1)[__c] : \
                          (__ctype2 + 1)[(unsigned char)(__c)]) & _R)
#define isgraph(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype2 + 1)[__c] : \
                          (__ctype2 + 1)[(unsigned char)(__c)]) & _G)
#define iscntrl(c)      (((__c = (c)) == _EOF_ ? \
                          (__ctype + 1)[__c] : \
                          (__ctype + 1)[(unsigned char)(__c)]) & _C)
#define isalnum(c)      ((__c = (c)) == _EOF_ ? \
                          (((__ctype + 1)[__c] & (_U | _L | _N)) || \
                           ((__ctype2 + 1)[__c] & _A)) : \
                          (((__ctype + 1)[(unsigned char)__c] & (_U | _L |
_N)) || \
                           ((__ctype2 + 1)[(unsigned char)__c] & _A)))
#endif

#define isascii(c)      (!((c) & ~0177))
#define toascii(c)      ((c) & 0177)

#define _toupper(c)     ((__ctype + 258)[(unsigned char)(c)])
#define _tolower(c)     ((__ctype + 258)[(unsigned char)(c)])

#endif /* lint */


#ifdef __cplusplus
}
#endif

#endif /* _CTYPE_H */
#endif

The problem is not visible if I use the header <cctype> instead of <ctype.h>
since the definitions for the functions within <ctype.h> is overridden by
the corresponding definitions in namespace std of libstdc++.

The problem is also *not* visible if we use the native C++ compiler (CC). (
I have to make a small change in the executable though. I have to change the
header from <iostream> to <iostream.h> as <iostream> is not available. I
also have to remove the "std::" qualification before "cout", "cin" and
"endl" though I think that doesn't really matter??)

$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/i386-pc-sco3.2v5.0.5/3.0.3/specs
Configured with: ../gcc-3.0.3/configure --enable-shared --disable-multilib
--enable-languages=c,c++ --disable-threads
Thread model: single
gcc version 3.0.3

Any help will be greatly appreciated.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]