Skip to content

Commit

Permalink
Check that isascii() is true before doing any other isXXXXX() test
Browse files Browse the repository at this point in the history
The IRAF libc maintaines the array of character types as a `char[128]`. So,
any test that uses this array should ensure that the argument is in this
range. This is now done by preceding all tests with `isascii(c) &&`. Do avoid
side effects by using the argument twice, the macros are converted into normal
functions.

This solution basically means that everything above 127 is neither a
alphabetical value nor a punctuation mark; not even printable. However, the
tests in this range are locale specific, which is not handled anyway by IRAF.

The best solution here would however be to rely on the system libc `isXXXXX()`
tests; however they may be defined as macros in `/usr/include/ctype.h`, which
makes it difficult to include in an IRAF libc function.
  • Loading branch information
olebole committed Dec 9, 2017
1 parent 9590f45 commit b16cdec
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 12 deletions.
51 changes: 51 additions & 0 deletions sys/libc/ctype.c
Expand Up @@ -29,3 +29,54 @@ char u_ctype_[] = {
_L, _L, _L, _L, _L, _L, _L, _L,
_L, _L, _L, _P, _P, _P, _P, _C
};

int isalpha(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&(_U|_L));
}

int isupper(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&_U);
}

int islower(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&_L);
}

int isdigit(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&_N);
}

int isxdigit(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&(_N|_X));
}

int isspace(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&_S);
}

int ispunct(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&_P);
}

int isalnum(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&(_U|_L|_N));
}

int isprint(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&(_P|_U|_L|_N));
}

int iscntrl(int c)
{
return isascii(c) && ((u_ctype_+1)[(unsigned int)(c)]&_C);
}

23 changes: 11 additions & 12 deletions unix/hlib/libc/ctype.h
Expand Up @@ -9,20 +9,19 @@
#ifdef vms
globalvalue vms_ctype_defs;
#endif
extern char u_ctype_[];

#define isalpha(c) ((u_ctype_+1)[(unsigned int)(c)]&(_U|_L))
#define isupper(c) ((u_ctype_+1)[(unsigned int)(c)]&_U)
#define islower(c) ((u_ctype_+1)[(unsigned int)(c)]&_L)
#define isdigit(c) ((u_ctype_+1)[(unsigned int)(c)]&_N)
#define isxdigit(c) ((u_ctype_+1)[(unsigned int)(c)]&(_N|_X))
#define isspace(c) ((u_ctype_+1)[(unsigned int)(c)]&_S)
#define ispunct(c) ((u_ctype_+1)[(unsigned int)(c)]&_P)
#define isalnum(c) ((u_ctype_+1)[(unsigned int)(c)]&(_U|_L|_N))
#define isprint(c) ((u_ctype_+1)[(unsigned int)(c)]&(_P|_U|_L|_N))
#define iscntrl(c) ((u_ctype_+1)[(unsigned int)(c)]&_C)
#define isascii(c) ((unsigned)((int)(c))<=0177)
int isalpha(int c);
int isupper(int c);
int islower(int c);
int isdigit(int c);
int isxdigit(int c);
int isspace(int c);
int ispunct(int c);
int isalnum(int c);
int isprint(int c);
int iscntrl(int c);

#define isascii(c) ((unsigned)((int)(c))<=0177)
#define toupper(c) ((c)-'a'+'A')
#define tolower(c) ((c)-'A'+'a')
#define toascii(c) ((c)&0177)
Expand Down

0 comments on commit b16cdec

Please sign in to comment.