/* Copyright 1996 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* ctype.c: ANSI draft (X3J11 May 88) library code, section 4.3 */ /* Copyright (C) Codemist Ltd. */ /* Version 3a */ #include <ctype.h> #include "kernel.h" #include "territory.h" #include "swis.h" /* HIDDEN EXPORTs */ void _set_ctype(int); void _ctype_init(void); /* IL (illegal) is 0, but enhances readability. */ #define IL 0 #define _UX (__U+__X) #define _LX (__L+__X) #define _CS (__C+__S) /* control and space (e.g. tab) */ /* * MUST arrange that an array of ILs gets put into memory just before __ctype. * 4 copies for both byte sexes and to fill out a 32 bit word. This is * done elsewhere, in cl_data. */ extern unsigned char __ctype[256]; /* Certain library facilities defined by macros can be used even if the corresponding header file has not been included, if the macro is #undef'ed or if not followed by a '('. This means that they must exist as ordinary functions even if they are usually expanded as macros. Hence the following (note that this relies that <ctype.h> defines all the RHS's as macros to avoid defining fns as infinite loops): */ int (isalnum)(int c) { return isalnum(c); } int (isalpha)(int c) { return isalpha(c); } int (iscntrl)(int c) { return iscntrl(c); } int (isdigit)(int c) { return isdigit(c); } int (isgraph)(int c) { return isgraph(c); } int (islower)(int c) { return islower(c); } int (isprint)(int c) { return isprint(c); } int (ispunct)(int c) { return ispunct(c); } int (isspace)(int c) { return isspace(c); } int (isupper)(int c) { return isupper(c); } int (isxdigit)(int c) { return isxdigit(c); } int isblank(int c) { return isspace(c) && c != '\r' && c != '\n' && c != '\v' && c != '\f'; } static char *touppertbl, *tolowertbl; int toupper(int c) { return touppertbl ? touppertbl[c] : (islower(c) ? c + ('A' - 'a') : c); } int tolower(int c) { return tolowertbl ? tolowertbl[c] : (isupper(c) ? c + ('a' - 'A') : c); } #if 'A' == 193 /* ebcdic -- this test relies on NorCroft __C */ static unsigned char ctype[256] = { __C,__C,__C,__C, IL,_CS, IL,__C, IL, IL, IL,_CS,_CS,_CS,__C,__C, __C,__C,__C,__C, IL, IL,__C, IL,__C,__C, IL, IL,__C,__C,__C,__C, IL, IL, IL, IL, IL,_CS,__C,__C, IL, IL, IL, IL, IL,__C,__C,__C, IL, IL,__C, IL, IL, IL, IL,__C, IL, IL, IL, IL,__C,__C, IL, IL, __B+__S, IL, IL, IL, IL, IL, IL, IL, IL, IL, IL,__P,__P,__P,__P,__P, __P, IL, IL, IL, IL, IL, IL, IL, IL, IL,__P,__P,__P,__P,__P,__P, __P,__P, IL, IL, IL, IL, IL, IL, IL, IL, IL,__P,__P,__P,__P,__P, IL,__P, IL, IL, IL, IL, IL, IL, IL,__P,__P,__P,__P,__P,__P,__P, IL,_LX,_LX,_LX,_LX,_LX,_LX,__L,__L,__L, IL, IL, IL, IL, IL, IL, IL,__L,__L,__L,__L,__L,__L,__L,__L,__L, IL, IL, IL, IL, IL, IL, IL, IL,__L,__L,__L,__L,__L,__L,__L,__L, IL, IL, IL,__P, IL, IL, IL, IL, IL, IL, IL, IL, IL, IL, IL, IL, IL, IL, IL,__P, IL, IL, __P,_UX,_UX,_UX,_UX,_UX,_UX,__U,__U,__U, IL, IL, IL, IL, IL, IL, __P,__U,__U,__U,__U,__U,__U,__U,__U,__U, IL, IL, IL, IL, IL, IL, __P, IL,__U,__U,__U,__U,__U,__U,__U,__U, IL, IL, IL, IL, IL, IL, __N,__N,__N,__N,__N,__N,__N,__N,__N,__N, IL, IL, IL, IL, IL, IL }; #else /* ascii */ static unsigned char ctype[128] = { __C, /* nul */ __C, /* \001 */ __C, /* \002 */ __C, /* \003 */ __C, /* \004 */ __C, /* \005 */ __C, /* \006 */ __C, /* bell */ __C, /* backspace */ __C+__S, /* tab */ __C+__S, /* newline */ __C+__S, /* vtab */ __C+__S, /* formfeed */ __C+__S, /* return */ __C, /* \016 */ __C, /* \017 */ __C, /* \020 */ __C, /* \021 */ __C, /* \022 */ __C, /* \023 */ __C, /* \024 */ __C, /* \025 */ __C, /* \026 */ __C, /* \027 */ __C, /* \030 */ __C, /* \031 */ __C, /* \032 */ __C, /* \033 */ __C, /* \034 */ __C, /* \035 */ __C, /* \036 */ __C, /* \037 */ __B+__S, /* space */ __P, /* ! */ __P, /* " */ __P, /* # */ __P, /* $ */ __P, /* % */ __P, /* & */ __P, /* ' */ __P, /* ( */ __P, /* ) */ __P, /* * */ __P, /* + */ __P, /* , */ __P, /* - */ __P, /* . */ __P, /* / */ __N, /* 0 */ __N, /* 1 */ __N, /* 2 */ __N, /* 3 */ __N, /* 4 */ __N, /* 5 */ __N, /* 6 */ __N, /* 7 */ __N, /* 8 */ __N, /* 9 */ __P, /* : */ __P, /* ; */ __P, /* < */ __P, /* = */ __P, /* > */ __P, /* ? */ __P, /* @ */ __U+__X, /* A */ __U+__X, /* B */ __U+__X, /* C */ __U+__X, /* D */ __U+__X, /* E */ __U+__X, /* F */ __U, /* G */ __U, /* H */ __U, /* I */ __U, /* J */ __U, /* K */ __U, /* L */ __U, /* M */ __U, /* N */ __U, /* O */ __U, /* P */ __U, /* Q */ __U, /* R */ __U, /* S */ __U, /* T */ __U, /* U */ __U, /* V */ __U, /* W */ __U, /* X */ __U, /* Y */ __U, /* Z */ __P, /* [ */ __P, /* \ */ __P, /* ] */ __P, /* ^ */ __P, /* _ */ __P, /* ` */ __L+__X, /* a */ __L+__X, /* b */ __L+__X, /* c */ __L+__X, /* d */ __L+__X, /* e */ __L+__X, /* f */ __L, /* g */ __L, /* h */ __L, /* i */ __L, /* j */ __L, /* k */ __L, /* l */ __L, /* m */ __L, /* n */ __L, /* o */ __L, /* p */ __L, /* q */ __L, /* r */ __L, /* s */ __L, /* t */ __L, /* u */ __L, /* v */ __L, /* w */ __L, /* x */ __L, /* y */ __L, /* z */ __P, /* { */ __P, /* | */ __P, /* } */ __P, /* ~ */ __C /* \177 */ }; #endif static unsigned int null_property_table[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned int *getpropertytable(int territory, int PROPERTY_CODE) { _kernel_swi_regs r; r.r[0] = territory; r.r[1] = PROPERTY_CODE; if (_kernel_swi(Territory_CharacterPropertyTable, &r, &r)) return null_property_table; return (unsigned int *)r.r[0]; } static char *getcvttable(int territory, int swi) { _kernel_swi_regs r; r.r[0] = territory; if (_kernel_swi(swi, &r, &r)) return 0; return (char *)r.r[0]; } void _set_ctype(int territory) { unsigned int i, j; /* unsigned is cue to division */ unsigned int *ctltable, *uctable, *lctable, *ptable, *stable; unsigned int ctlw, ucw, lcw, pw, sw; if (!territory) { for (j = 0; j < sizeof(ctype); j++) __ctype[j] = ctype[j]; #if 'A' != 193 for (j = 128; j < 256; j++) __ctype[j] = IL; #endif touppertbl = 0; tolowertbl = 0; } else { /* Get property tables - these are byte sex dependant */ ctltable = getpropertytable(territory, TERRITORY_PROPERTY_CONTROL); uctable = getpropertytable(territory, TERRITORY_PROPERTY_UPPERCASE); lctable = getpropertytable(territory, TERRITORY_PROPERTY_LOWERCASE); ptable = getpropertytable(territory, TERRITORY_PROPERTY_PUNCTUATION); stable = getpropertytable(territory, TERRITORY_PROPERTY_SPACE); j = 0; /* Check to see this generates sensible assembler */ for (i = 0; i < 256 / 32; i++) { ctlw = ctltable[i]; ucw = uctable[i]; lcw = lctable[i]; pw = ptable[i]; sw = stable[i]; do { __ctype[j] = (ctlw & 1) * __C | (ucw & 1) * __U | (lcw & 1) * __L | (pw & 1) * __P | (sw & 1) * __S; /* Non-control space characters get the __B flag - this makes * them printable (eg non-breaking space). */ if ((__ctype[j] & __S) && !(__ctype[j] & __C)) __ctype[j] |= __B; ctlw >>= 1; ucw >>= 1; lcw >>= 1; pw >>= 1; sw >>= 1; } while (++j & 0x1f); } /* Unfortunately ANSI actually DEFINE what digits are ! * But I want to use Roman numerals :-) * Numbers are in a block together even in EBCIDIC */ for (j = '0'; j <= '9'; j++) __ctype[j] |= __N; /* Similarly they say what xdigit is * 'A' - 'F' & 'a' - 'f' also occur in a block in EBCIDIC */ for (j = 'A'; j <= 'F'; j++) { __ctype[j] |= __X; __ctype[j + 'a' - 'A'] |= __X; } /* Because of ANSI restriction wrt isgraph and isprint __C is the only */ /* allowable flag from the territory properties */ __ctype[' '] = (__ctype[' '] & __C) | __B | __S; touppertbl = getcvttable(territory, Territory_UpperCaseTable); tolowertbl = getcvttable(territory, Territory_LowerCaseTable); } } void _ctype_init() { __ctype[-1] = IL; /* for ctype(EOF) */ _set_ctype(0); } /* End of ctype.c */