zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: remove ancient STOUC() workaround
@ 2022-12-14 16:52 Oliver Kiddle
  2022-12-14 17:07 ` Peter Stephenson
  0 siblings, 1 reply; 2+ messages in thread
From: Oliver Kiddle @ 2022-12-14 16:52 UTC (permalink / raw)
  To: Zsh workers

The STOUC() macro is a wrapper for (unsigned char) casts that works
around a compiler bug by doing ((unsigned char)(unsigned short)(X)) if
autoconf detects the bug. This has been there since before the earliest
(1995) list archives. I've never come across the need for this in any
other C codebase. Surely whatever compiler needed this has long since
ceased to be able to compile zsh for a myriad other reasons and been
confined to a museum. A web search for the autoconf output of "signed to
unsigned casting is broken..." finds matches with the word "no" but none
with "yes". Or is there some further need for this that I'm missing?

The cost of keeping this may seem negligible: it doesn't affect the
runtime. But I'd argue that there is a cost in terms of making our code
just a tiny bit less accessable for anyone coming to it anew.

The vast majority of the patch below is generated using a symbolic
patch and coccinelle. I have more confidence in coccinelle to get
this right vs. using sed and a regular expression. I've done a
build/test with -fsigned-char and -funsigned-char.

Just above the removed reference to STOUC() in the zsh-development-guide
is a style recommendation for a space after type casts. This rule
appears to have been flouted more than most but I have applied it in
this patch.

Oliver

diff --git a/Etc/zsh-development-guide b/Etc/zsh-development-guide
index e8c292cfd..565b0b1d9 100644
--- a/Etc/zsh-development-guide
+++ b/Etc/zsh-development-guide
@@ -223,9 +223,6 @@ C coding style
 * Do not use space between the function name and the opening parenthesis.
   Use space after if/for/while.  Use space after type casts.
 
-* Do not use (unsigned char) casts since some compilers do not handle
-  them properly.  Use the provided STOUC(X) macro instead.
-
 * If you use emacs 19.30 or newer you can put the following line to your
   ~/.emacs file to make these formatting rules the default:
 
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index e46903916..ad17ed65f 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -1426,10 +1426,10 @@ zccmd_querychar(const char *nam, char **args)
     inc &= A_CHARTEXT;
     if (imeta(inc)) {
 	instr[0] = Meta;
-	instr[1] = STOUC(inc ^ 32);
+	instr[1] = (unsigned char) (inc ^ 32);
 	instr[2] = '\0';
     } else {
-	instr[0] = STOUC(inc);
+  	instr[0] = (unsigned char) inc;
 	instr[1] = '\0';
     }
     attrs = inc;
diff --git a/Src/Modules/stat.c b/Src/Modules/stat.c
index 0df9b35b7..c9f851974 100644
--- a/Src/Modules/stat.c
+++ b/Src/Modules/stat.c
@@ -406,7 +406,7 @@ bin_stat(char *name, char **args, Options ops, UNUSED(int func))
 	} else {
 	    for (; *arg; arg++) {
 		if (strchr("glLnNorstT", *arg))
-		    ops->ind[STOUC(*arg)] = 1;
+		    ops->ind[(unsigned char) *arg] = 1;
 		else if (*arg == 'A') {
 		    if (arg[1]) {
 			arrnam = arg+1;
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index e8e239e76..49b3ffa89 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -944,9 +944,9 @@ zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep)
 		return 1;
 	    }
 	    for (i = 0; i < 4; i++)
-		iaddr[i] = STOUC(nums[i]);
-	    iport[0] = STOUC(nums[4]);
-	    iport[1] = STOUC(nums[5]);
+		iaddr[i] = (unsigned char) nums[i];
+	    iport[0] = (unsigned char) nums[4];
+	    iport[1] = (unsigned char) nums[5];
 
 	    memcpy(&zdsockp->in.sin_addr, iaddr, sizeof(iaddr));
 	    memcpy(&zdsockp->in.sin_port, iport, sizeof(iport));
@@ -2438,7 +2438,7 @@ zftp_type(char *name, char **args, int flags)
 	fflush(stdout);
 	return 0;
     } else {
-	nt = toupper(STOUC(*str));
+	nt = toupper((unsigned char) *str);
 	/*
 	 * RFC959 specifies other types, but these are the only
 	 * ones we know what to do with.
@@ -2472,7 +2472,7 @@ zftp_mode(char *name, char **args, UNUSED(int flags))
 	fflush(stdout);
 	return 0;
     }
-    nt = str[0] = toupper(STOUC(*str));
+    nt = str[0] = toupper((unsigned char) *str);
     if (str[1] || (nt != 'S' && nt != 'B')) {
 	zwarnnam(name, "transfer mode %s not recognised", str);
 	return 1;
@@ -3075,7 +3075,7 @@ bin_zftp(char *name, char **args, UNUSED(Options ops), UNUSED(int func))
     if ((prefs = getsparam_u("ZFTP_PREFS"))) {
 	zfprefs = 0;
 	for (ptr = prefs; *ptr; ptr++) {
-	    switch (toupper(STOUC(*ptr))) {
+	    switch (toupper((unsigned char) *ptr)) {
 	    case 'S':
 		/* sendport */
 		zfprefs |= ZFPF_SNDP;
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index dfd2a2a7a..c2656698c 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -638,7 +638,7 @@ ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch)
 		readchar = cmd->read;
 		cmd->read = -1;
 	    } else
-		readchar = STOUC(buf[used]);
+		readchar = (unsigned char) buf[used];
 	    if (imeta(readchar)) {
 		buf[used++] = Meta;
 		buf[used++] = (char) (readchar ^ 32);
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 2f17c03f1..8a7d0a4c5 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -795,11 +795,11 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
 
 	    if (idigit(*s)) {
 		for (min = 0; idigit(*s); s++)
-		    min = (min * 10) + (int) STOUC(*s) - '0';
+		    min = (min * 10) + (int) (unsigned char) *s - '0';
 	    }
 
 	    /* Ternary expressions */
-	    testit = (STOUC(*s) == '(');
+	    testit = ((unsigned char) *s == '(');
 	    if (testit && s[1] == '-')
 	    {
 		/* Allow %(-1... etc. */
@@ -808,25 +808,25 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
 	    }
 	    if ((*s == '.' || testit) && idigit(s[1])) {
 		for (max = 0, s++; idigit(*s); s++)
-		    max = (max * 10) + (int) STOUC(*s) - '0';
+		    max = (max * 10) + (int) (unsigned char) *s - '0';
 	    } else if (*s == '.' || testit)
 		s++;
 
-	    if (testit && STOUC(*s)) {
+	    if (testit && (unsigned char) *s) {
 		int actval, testval, endcharl;
 
 		/* Only one number is useful for ternary expressions. */
 		testval = (min >= 0) ? min : (max >= 0) ? max : 0;
 
-		if (specs[STOUC(*s)] && *specs[STOUC(*s)]) {
+		if (specs[(unsigned char) *s] && *specs[(unsigned char) *s]) {
 		    if (presence) {
 			if (testval)
 #ifdef MULTIBYTE_SUPPORT
 			    if (isset(MULTIBYTE))
-				actval = MB_METASTRWIDTH(specs[STOUC(*s)]);
+				actval = MB_METASTRWIDTH(specs[(unsigned char) *s]);
 			    else
 #endif
-				actval = strlen(specs[STOUC(*s)]);
+				actval = strlen(specs[(unsigned char) *s]);
 		        else
 			    actval = 1;
 			actval = right ? (testval < actval) : (testval >= actval);
@@ -834,7 +834,7 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
 			if (right) /* put the sign back */
 			    testval *= -1;
 			/* zero means values are equal, i.e. true */
-			actval = (int)mathevali(specs[STOUC(*s)]) - testval;
+			actval = (int) mathevali(specs[(unsigned char) *s]) - testval;
 		    }
 		} else
 		    actval = presence ? !right : testval;
@@ -855,7 +855,7 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
 		    return NULL;
 	    } else if (skip) {
 		continue;
-	    } else if ((spec = specs[STOUC(*s)])) {
+	    } else if ((spec = specs[(unsigned char) *s])) {
 		int len;
 
 		if ((len = strlen(spec)) > max && max >= 0)
@@ -950,7 +950,7 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 		    zwarnnam(nam, "invalid argument: %s", *ap);
 		    return 1;
 		}
-		specs[STOUC(ap[0][0])] = ap[0] + 2;
+		specs[(unsigned char) ap[0][0]] = ap[0] + 2;
 	    }
 	    out = (char *) zhalloc(olen = 128);
 
@@ -1864,7 +1864,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 	d->vals = d->last = NULL;
 	opt_descs = d;
 	if (!o[1])
-	    sopts[STOUC(*o)] = d;
+	    sopts[(unsigned char) *o] = d;
 	if ((flags & ZOF_MAP) && !map_opt_desc(d)) {
 	    zwarnnam(nam, "cyclic option mapping: %s", args[-1]);
 	    return 1;
@@ -1888,7 +1888,7 @@ bin_zparseopts(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 	}
 	if (!(d = lookup_opt(o + 1))) {
 	    while (*++o) {
-		if (!(d = sopts[STOUC(*o)])) {
+		if (!(d = sopts[(unsigned char) *o])) {
 		    if (fail) {
 			if (*o != '-')
 			    zwarnnam(nam, "bad option: -%c", *o);
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 4ac5d089f..64a860fa3 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -2898,9 +2898,9 @@ add_match_data(int alt, char *str, char *orig, Cline line,
 		*t++ = '$';
 		*t++ = '\'';
 		*t++ = '\\';
-		*t++ = '0' + ((STOUC(curchar) >> 6) & 7);
-		*t++ = '0' + ((STOUC(curchar) >> 3) & 7);
-		*t++ = '0' + (STOUC(curchar) & 7);
+		*t++ = '0' + (((unsigned char) curchar >> 6) & 7);
+		*t++ = '0' + (((unsigned char) curchar >> 3) & 7);
+		*t++ = '0' + ((unsigned char) curchar & 7);
 		*t++ = '\'';
 	    } while (cnt == MB_INCOMPLETE && fs < fe);
 	    /* Scanning restarts from the spot after the char we skipped. */
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index 67a60963e..96ad7b3f1 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -518,7 +518,7 @@ parse_class(Cpattern p, char *iptr)
 	    ch = range_type((char *)iptr, nptr-iptr);
 	    iptr = nptr + 2;
 	    if (ch != PP_UNKWN)
-		*optr++ = STOUC(Meta) + ch;
+		*optr++ = (unsigned char) Meta + ch;
 	} else {
 	    /* characters stay metafied */
 	    char *ptr1 = iptr;
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index 0dc64db6a..6e0eac31f 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -291,12 +291,12 @@ getcolval(char *s, int multi)
 	    case '?': *p = '\177'; break;
 	    default:
 		if (*s >= '0' && *s <= '7') {
-		    int i = STOUC(*s);
+		    int i = (unsigned char) *s;
 
 		    if (*++s >= '0' && *s <= '7') {
-			i = (i * 8) + STOUC(*s);
+			i = (i * 8) + (unsigned char) *s;
 			if (*++s >= '0' && *s <= '7')
-			    i = (i * 8) + STOUC(*s);
+			    i = (i * 8) + (unsigned char) *s;
 		    }
 		    *p = (char) i;
 		} else
@@ -305,7 +305,7 @@ getcolval(char *s, int multi)
 	} else if (*s == '^') {
 	    if ((s[1] >= '@' && s[1] <= '_') ||
 		(s[1] >= 'a' && s[1] <= 'z'))
-		*p = (char) (STOUC(*s) & ~0x60);
+		*p = (char) ((unsigned char) *s & ~0x60);
 	    else if (s[1] == '?')
 		*p = '\177';
 	    else {
@@ -794,7 +794,7 @@ clnicezputs(int do_colors, char *s, int ml)
 	 */
 	for (t = sptr; *t; t++) {
 	    /* Input is metafied... */
-	    int nc = (*t == Meta) ? STOUC(*++t ^ 32) : STOUC(*t);
+	    int nc = (*t == Meta) ? (unsigned char) (*++t ^ 32) : (unsigned char) *t;
 	    /* Is the screen full? */
 	    if (ml == mlend - 1 && col == zterm_columns - 1) {
 		mlprinted = ml - oml;
@@ -852,7 +852,7 @@ clnicezputs(int do_colors, char *s, int ml)
 	    cc = *s++ ^ 32;
 
 	for (t = nicechar(cc); *t; t++) {
-	    int nc = (*t == Meta) ? STOUC(*++t ^ 32) : STOUC(*t);
+	    int nc = (*t == Meta) ? (unsigned char) (*++t ^ 32) : (unsigned char) *t;
 	    if (ml == mlend - 1 && col == zterm_columns - 1) {
 		mlprinted = ml - oml;
 		return 0;
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index f59545397..97cc7d797 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -526,7 +526,7 @@ typedef REFRESH_ELEMENT *REFRESH_STRING;
     ((int)((unsigned)(x) - ZSH_INVALID_WCHAR_BASE))
 /* Turn a single byte character into a private wide character */
 #define ZSH_CHAR_TO_INVALID_WCHAR(x)			\
-    ((wchar_t)(STOUC(x) + ZSH_INVALID_WCHAR_BASE))
+    ((wchar_t)((unsigned char) x + ZSH_INVALID_WCHAR_BASE))
 #endif
 
 
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index d90838f03..b2375a15e 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -404,7 +404,7 @@ static void
 scankeys(HashNode hn, UNUSED(int flags))
 {
     Key k = (Key) hn;
-    int f = k->nam[0] == Meta ? STOUC(k->nam[1])^32 : STOUC(k->nam[0]);
+    int f = k->nam[0] == Meta ? (unsigned char) k->nam[1]^32 : (unsigned char) k->nam[0];
     char m[3];
 
     while(skm_last < f) {
@@ -566,7 +566,7 @@ mod_export int
 bindkey(Keymap km, const char *seq, Thingy bind, char *str)
 {
     Key k;
-    int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]);
+    int f = seq[0] == Meta ? (unsigned char) seq[1]^32 : (unsigned char) seq[0];
     char *buf, *ptr;
 
     if(km->flags & KM_IMMUTABLE)
@@ -661,7 +661,7 @@ keybind(Keymap km, char *seq, char **strp)
     Key k;
 
     if(ztrlen(seq) == 1) {
-	int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]);
+	int f = seq[0] == Meta ? (unsigned char) seq[1]^32 : (unsigned char) seq[0];
 	Thingy bind = km->first[f];
 
 	if(bind)
@@ -687,7 +687,7 @@ keyisprefix(Keymap km, char *seq)
     if(!*seq)
 	return 1;
     if(ztrlen(seq) == 1) {
-	int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]);
+	int f = seq[0] == Meta ? (unsigned char) seq[1]^32 : (unsigned char) seq[0];
 
 	if(km->first[f])
 	    return 0;
@@ -764,10 +764,10 @@ bin_bindkey(char *name, char **argv, Options ops, UNUSED(int func))
     int n;
 
     /* select operation and ensure no clashing arguments */
-    for(op = opns; op->o && !OPT_ISSET(ops,STOUC(op->o)); op++) ;
+    for(op = opns; op->o && !OPT_ISSET(ops,(unsigned char) op->o); op++) ;
     if(op->o)
 	for(opp = op; (++opp)->o; )
-	    if(OPT_ISSET(ops,STOUC(opp->o))) {
+	    if(OPT_ISSET(ops,(unsigned char) opp->o)) {
 		zwarnnam(name, "incompatible operation selection options");
 		return 1;
 	    }
@@ -1049,7 +1049,7 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, Options ops,
 	    char m[3];
 
 	    if(len < 2 || len > 2 + (bseq[1] == '-') ||
-	       (first = STOUC(bseq[0])) > (last = STOUC(bseq[len - 1]))) {
+	       (first = (unsigned char) bseq[0]) > (last = (unsigned char) bseq[len - 1])) {
 		zwarnnam(name, "malformed key range `%s'", useq);
 		ret = 1;
 	    } else {
@@ -1149,8 +1149,8 @@ scanbindlist(char *seq, Thingy bind, char *str, void *magic)
     if(bind == bs->bind && (bind || !strcmp(str, bs->str)) &&
        ztrlen(seq) == 1 && ztrlen(bs->lastseq) == 1) {
 	int l = bs->lastseq[1] ?
-	    STOUC(bs->lastseq[1]) ^ 32 : STOUC(bs->lastseq[0]);
-	int t = seq[1] ? STOUC(seq[1]) ^ 32 : STOUC(seq[0]);
+	    (unsigned char) bs->lastseq[1] ^ 32 : (unsigned char) bs->lastseq[0];
+	int t = seq[1] ? (unsigned char) seq[1] ^ 32 : (unsigned char) seq[0];
 
 	if(t == l + 1) {
 	    zsfree(bs->lastseq);
@@ -1526,10 +1526,10 @@ getrestchar_keybuf(void)
      */
     while (1) {
 	if (bufind < buflen) {
-	    c = STOUC(keybuf[bufind++]);
+	    c = (unsigned char) keybuf[bufind++];
 	    if (c == Meta) {
 		DPUTS(bufind == buflen, "Meta at end of keybuf");
-		c = STOUC(keybuf[bufind++]) ^ 32;
+		c = (unsigned char) keybuf[bufind++] ^ 32;
 	    }
 	} else {
 	    /*
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 9edf30e01..40b902901 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -876,7 +876,7 @@ getbyte(long do_keytmout, int *timeout, int full)
 #endif
 
     if (kungetct)
-	ret = STOUC(kungetbuf[--kungetct]);
+	ret = (unsigned char) kungetbuf[--kungetct];
     else {
 	for (;;) {
 	    int q = queue_signal_level();
@@ -940,7 +940,7 @@ getbyte(long do_keytmout, int *timeout, int full)
 	else if (cc == '\n')
 	    cc = '\r';
 
-	ret = STOUC(cc);
+	ret = (unsigned char) cc;
     }
     /*
      * curvichg.buf is raw bytes, not wide characters, so is dealt
diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index cd3f2c356..1b036a8a0 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -366,10 +366,10 @@ bin_zle(char *name, char **args, Options ops, UNUSED(int func))
     int n;
 
     /* select operation and ensure no clashing arguments */
-    for(op = opns; op->o && !OPT_ISSET(ops,STOUC(op->o)); op++) ;
+    for(op = opns; op->o && !OPT_ISSET(ops, (unsigned char) op->o); op++) ;
     if(op->o)
 	for(opp = op; (++opp)->o; )
-	    if(OPT_ISSET(ops,STOUC(opp->o))) {
+	    if(OPT_ISSET(ops, (unsigned char) opp->o)) {
 		zwarnnam(name, "incompatible operation selection options");
 		return 1;
 	    }
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 3d9017dcf..2536e9faa 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -1265,7 +1265,7 @@ bindztrdup(char *str)
     char *buf, *ptr, *ret;
 
     for(ptr = str; *ptr; ptr++) {
-	c = *ptr == Meta ? STOUC(*++ptr) ^ 32 : STOUC(*ptr);
+	c = *ptr == Meta ? (unsigned char) *++ptr ^ 32 : (unsigned char) *ptr;
 	if(c & 0x80) {
 	    len += 3;
 	    c &= 0x7f;
@@ -1279,7 +1279,7 @@ bindztrdup(char *str)
     }
     ptr = buf = zalloc(len);
     for(; *str; str++) {
-	c = *str == Meta ? STOUC(*++str) ^ 32 : STOUC(*str);
+	c = *str == Meta ? (unsigned char) *++str ^ 32 : (unsigned char) *str;
 	if(c & 0x80) {
 	    *ptr++ = '\\';
 	    *ptr++ = 'M';
diff --git a/Src/builtin.c b/Src/builtin.c
index a7b7755a7..db83313d6 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2634,7 +2634,7 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
      * these flags are defined in zsh.h         */
     for (; *optstr; optstr++, bit <<= 1)
     {
-	int optval = STOUC(*optstr);
+	int optval = (unsigned char) *optstr;
 	if (OPT_MINUS(ops,optval))
 	    on |= bit;
 	else if (OPT_PLUS(ops,optval))
@@ -4752,7 +4752,7 @@ bin_print(char *name, char **args, Options ops, int func)
 		     */
 		    if (*aptr == '\033' || *aptr == '\233') {
 			for (aptr++, l--;
-			     l && !isalpha(STOUC(*aptr));
+			     l && !isalpha((unsigned char) (*aptr));
 			     aptr++, l--)
 			    ;
 			aptr++;
@@ -5313,9 +5313,9 @@ bin_print(char *name, char **args, Options ops, int func)
 		    else
 			cc = WEOF;
 		    if (cc == WEOF)
-			cc = (curlen > 1) ? STOUC(curarg[1]) : 0;
+			cc = (curlen > 1) ? (unsigned char) (curarg[1]) : 0;
 #else
-		    cc = (curlen > 1) ? STOUC(curarg[1]) : 0;
+		    cc = (curlen > 1) ? (unsigned char) (curarg[1]) : 0;
 #endif
 		    if (type == 2) {
 			doubleval = cc;
@@ -6685,7 +6685,7 @@ bin_read(char *name, char **args, Options ops, UNUSED(int func))
 		    continue;
 		first = 0;
 	    }
-	    if (imeta(STOUC(*bptr))) {
+	    if (imeta((unsigned char) *bptr)) {
 		bptr[1] = bptr[0] ^ 32;
 		bptr[0] = Meta;
 		bptr += 2;
@@ -6878,7 +6878,7 @@ bin_read(char *name, char **args, Options ops, UNUSED(int func))
 		if (bslash)
 		    continue;
 	    }
-	    if (imeta(STOUC(*bptr))) {
+	    if (imeta((unsigned char) *bptr)) {
 		bptr[1] = bptr[0] ^ 32;
 		bptr[0] = Meta;
 		bptr += 2;
@@ -7000,14 +7000,14 @@ zread(int izle, int *readchar, long izle_timeout)
 	   buffer.  This may be a null byte to indicate EOF.  If reading from the
 	   buffer, move on the buffer pointer. */
 	if (*zbuf == Meta)
-	    return zbuf++, STOUC(*zbuf++ ^ 32);
+	    return zbuf++, (unsigned char) (*zbuf++ ^ 32);
 	else
-	    return (*zbuf) ? STOUC(*zbuf++) : EOF;
+	    return (*zbuf) ? (unsigned char) *zbuf++ : EOF;
     }
     if (*readchar >= 0) {
 	cc = *readchar;
 	*readchar = -1;
-	return STOUC(cc);
+	return (unsigned char) cc;
     }
     for (;;) {
 	/* read a character from readfd */
@@ -7015,7 +7015,7 @@ zread(int izle, int *readchar, long izle_timeout)
 	switch (ret) {
 	case 1:
 	    /* return the character read */
-	    return STOUC(cc);
+	    return (unsigned char) cc;
 	case -1:
 #if defined(EAGAIN) || defined(EWOULDBLOCK)
 	    if (!retry && readfd == 0 && (
diff --git a/Src/exec.c b/Src/exec.c
index 2b7e0c7c5..c8eb71b34 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -603,7 +603,7 @@ zexecve(char *pth, char **argv, char **newenvp)
                         isbinary = 1;
                         hasletter = 0;
                         for (ptr = execvebuf; ptr < ptr2; ptr++) {
-                            if (islower(STOUC(*ptr)) || *ptr == '$' || *ptr == '`')
+			    if (islower((unsigned char) *ptr) || *ptr == '$' || *ptr == '`')
                                 hasletter = 1;
                             if (hasletter && *ptr == '\n') {
                                 isbinary = 0;
diff --git a/Src/glob.c b/Src/glob.c
index 490bafc37..63f8a5fa7 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -2418,11 +2418,11 @@ xpandbraces(LinkList list, LinkNode *np)
 	memset(ccl, 0, sizeof(ccl) / sizeof(ccl[0]));
 	for (p = str + 1; p < str2;) {
 	    if (itok(c1 = *p++))
-		c1 = ztokens[c1 - STOUC(Pound)];
+		c1 = ztokens[c1 - (unsigned char) Pound];
 	    if ((char) c1 == Meta)
 		c1 = 32 ^ *p++;
 	    if (itok(c2 = *p))
-		c2 = ztokens[c2 - STOUC(Pound)];
+		c2 = ztokens[c2 - (unsigned char) Pound];
 	    if ((char) c2 == Meta)
 		c2 = 32 ^ p[1];
 	    if (IS_DASH((char)c1) && lastch >= 0 &&
diff --git a/Src/hist.c b/Src/hist.c
index bff0abe61..82d03a840 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -2235,7 +2235,7 @@ casemodify(char *str, int how)
 		char *mbptr;
 
 		for (mbptr = mbstr; mbptr < mbstr + len2; mbptr++) {
-		    if (imeta(STOUC(*mbptr))) {
+		    if (imeta((unsigned char) *mbptr)) {
 			*ptr2++ = Meta;
 			*ptr2++ = *mbptr ^ 32;
 		    } else
@@ -2254,10 +2254,10 @@ casemodify(char *str, int how)
 	    int c;
 	    int mod = 0;
 	    if (*str == Meta) {
-		c = STOUC(str[1] ^ 32);
+		c = (unsigned char) (str[1] ^ 32);
 		str += 2;
 	    } else
-		c = STOUC(*str++);
+		c = (unsigned char) *str++;
 	    switch (how) {
 	    case CASMOD_LOWER:
 		if (isupper(c)) {
diff --git a/Src/init.c b/Src/init.c
index 871d46b12..9981d059a 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -500,10 +500,10 @@ parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp,
 		    }
 		}
               break;
-	    } else if (isspace(STOUC(**argv))) {
+	    } else if (isspace((unsigned char) **argv)) {
 		/* zsh's typtab not yet set, have to use ctype */
 		while (*++*argv)
-		    if (!isspace(STOUC(**argv))) {
+		    if (!isspace((unsigned char) **argv)) {
 		     badoptionstring:
 			WARN_OPTION("bad option string: '%s'", args);
 			return 1;
@@ -1724,9 +1724,9 @@ zsh_main(UNUSED(int argc), char **argv)
      * interactive
      */
     typtab['\0'] |= IMETA;
-    typtab[STOUC(Meta)  ] |= IMETA;
-    typtab[STOUC(Marker)] |= IMETA;
-    for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
+    typtab[(unsigned char) Meta  ] |= IMETA;
+    typtab[(unsigned char) Marker] |= IMETA;
+    for (t0 = (int) (unsigned char) Pound; t0 <= (int) (unsigned char) Nularg; t0++)
 	typtab[t0] |= ITOK | IMETA;
 
     for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++);
diff --git a/Src/input.c b/Src/input.c
index 9898a7177..d55b05696 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -220,7 +220,7 @@ shingetchar(void)
     int nread, rsize = isset(SHINSTDIN) ? 1 : SHINBUFSIZE;
 
     if (shinbufptr < shinbufendptr)
-	return STOUC(*shinbufptr++);
+	return (unsigned char) *shinbufptr++;
 
     shinbufreset();
 #ifdef USE_LSEEK
@@ -242,7 +242,7 @@ shingetchar(void)
 		zerr("lseek(%d, %d): %e", SHIN, -(nread - rsize), errno);
 	} else
 	    shinbufendptr = shinbuffer + nread;
-	return STOUC(*shinbufptr++);
+	return (unsigned char) *shinbufptr++;
     }
 #endif
     for (;;) {
@@ -259,7 +259,7 @@ shingetchar(void)
     }
     if (shinbufendptr == shinbuffer)
         return -1;
-    return STOUC(*shinbufptr++);
+    return (unsigned char) *shinbufptr++;
 }
 
 /* Read a line from SHIN.  Convert tokens and   *
@@ -328,7 +328,7 @@ ingetc(void)
 	if (inbufleft) {
 	    inbufleft--;
 	    inbufct--;
-	    if (itok(lastc = STOUC(*inbufptr++)))
+	    if (itok(lastc = (unsigned char) *inbufptr++))
 		continue;
 	    if (((inbufflags & INP_LINENO) || !strin) && lastc == '\n')
 		lineno++;
diff --git a/Src/lex.c b/Src/lex.c
index e2f8bcfb1..15da85a93 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -423,7 +423,7 @@ initlextabs(void)
     for (t0 = 0; lx2[t0]; t0++)
 	lexact2[(int)lx2[t0]] = t0;
     lexact2['&'] = LX2_BREAK;
-    lexact2[STOUC(Meta)] = LX2_META;
+    lexact2[(unsigned char) Meta] = LX2_META;
     lextok2['*'] = Star;
     lextok2['?'] = Quest;
     lextok2['{'] = Inbrace;
@@ -722,7 +722,7 @@ gettok(void)
 	}
 	return peek;
     }
-    switch (lexact1[STOUC(c)]) {
+    switch (lexact1[(unsigned char) c]) {
     case LX1_BKSLASH:
 	d = hgetc();
 	if (d == '\n')
@@ -960,8 +960,8 @@ gettokstr(int c, int sub)
 	if (inbl && !in_brace_param && !pct)
 	    act = LX2_BREAK;
 	else {
-	    act = lexact2[STOUC(c)];
-	    c = lextok2[STOUC(c)];
+	    act = lexact2[(unsigned char) c];
+	    c = lextok2[(unsigned char) c];
 	}
 	switch (act) {
 	case LX2_BREAK:
@@ -1263,7 +1263,7 @@ gettokstr(int c, int sub)
 		    continue;
 	    } else {
 		add(Bnull);
-		if (c == STOUC(Meta)) {
+		if (c == (unsigned char) Meta) {
 		    c = hgetc();
 #ifdef DEBUG
 		    if (lexstop) {
diff --git a/Src/math.c b/Src/math.c
index 777ad9c31..12c8d6f6b 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -955,7 +955,7 @@ getcvar(char *s)
 	    }
 	}
 #endif
-	mn.u.l = STOUC(*t == Meta ? t[1] ^ 32 : *t);
+	mn.u.l = (unsigned char) (*t == Meta ? t[1] ^ 32 : *t);
     }
     unqueue_signals();
     return mn;
diff --git a/Src/module.c b/Src/module.c
index bab4d8d73..6cf442270 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -2474,7 +2474,7 @@ bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func))
 	return 1;
     }
     for (fp = fonly; *fp; fp++) {
-	if (OPT_ISSET(ops,STOUC(*fp)) && !OPT_ISSET(ops,'F')) {
+	if (OPT_ISSET(ops,(unsigned char) *fp) && !OPT_ISSET(ops,'F')) {
 	    zwarnnam(nam, "-%c is only allowed with -F", *fp);
 	    return 1;
 	}
diff --git a/Src/params.c b/Src/params.c
index f1fe38955..2e4a6eae2 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -732,7 +732,7 @@ split_env_string(char *env, char **name, char **value)
 
     tenv = strcpy(zhalloc(strlen(env) + 1), env);
     for (str = tenv; *str && *str != '='; str++) {
-	if (STOUC(*str) >= 128) {
+	if ((unsigned char) *str >= 128) {
 	    /*
 	     * We'll ignore environment variables with names not
 	     * from the portable character set since we don't
@@ -4123,7 +4123,8 @@ char *
 tiedarrgetfn(Param pm)
 {
     struct tieddata *dptr = (struct tieddata *)pm->u.data;
-    return *dptr->arrptr ? zjoin(*dptr->arrptr, STOUC(dptr->joinchar), 1) : "";
+    return *dptr->arrptr ?
+	    zjoin(*dptr->arrptr, (unsigned char) dptr->joinchar, 1) : "";
 }
 
 /**/
@@ -4819,12 +4820,12 @@ keyboardhacksetfn(UNUSED(Param pm), char *x)
 	    zwarn("Only one KEYBOARD_HACK character can be defined");  /* could be changed if needed */
 	}
 	for (i = 0; i < len; i++) {
-	    if (!isascii(STOUC(x[i]))) {
+	    if (!isascii((unsigned char) x[i])) {
 		zwarn("KEYBOARD_HACK can only contain ASCII characters");
 		return;
 	    }
 	}
-	keyboardhackchar = len ? STOUC(x[0]) : '\0';
+	keyboardhackchar = len ? (unsigned char) x[0] : '\0';
 	free(x);
     } else
 	keyboardhackchar = '\0';
@@ -4858,14 +4859,14 @@ histcharssetfn(UNUSED(Param pm), char *x)
 	if (len > 3)
 	    len = 3;
 	for (i = 0; i < len; i++) {
-	    if (!isascii(STOUC(x[i]))) {
+	    if (!isascii((unsigned char) x[i])) {
 		zwarn("HISTCHARS can only contain ASCII characters");
 		return;
 	    }
 	}
-	bangchar = len ? STOUC(x[0]) : '\0';
-	hatchar =  len > 1 ? STOUC(x[1]) : '\0';
-	hashchar = len > 2 ? STOUC(x[2]) : '\0';
+	bangchar = len ? (unsigned char) x[0] : '\0';
+	hatchar =  len > 1 ? (unsigned char) x[1] : '\0';
+	hashchar = len > 2 ? (unsigned char) x[2] : '\0';
 	free(x);
     } else {
 	bangchar = '!';
@@ -5087,7 +5088,7 @@ arrfixenv(char *s, char **t)
     if (pm->node.flags & PM_SPECIAL)
 	joinchar = ':';
     else
-	joinchar = STOUC(((struct tieddata *)pm->u.data)->joinchar);
+	joinchar = (unsigned char) ((struct tieddata *)pm->u.data)->joinchar;
 
     addenv(pm, t ? zjoin(t, joinchar, 1) : "");
 }
@@ -5109,9 +5110,9 @@ zputenv(char *str)
     char *ptr;
     int ret;
 
-    for (ptr = str; *ptr && STOUC(*ptr) < 128 && *ptr != '='; ptr++)
+    for (ptr = str; *ptr && (unsigned char) *ptr < 128 && *ptr != '='; ptr++)
 	;
-    if (STOUC(*ptr) >= 128) {
+    if ((unsigned char) *ptr >= 128) {
 	/*
 	 * Environment variables not in the portable character
 	 * set are non-standard and we don't really know of
@@ -6022,7 +6023,7 @@ printparamnode(HashNode hn, int printflags)
 	 * append the join char for tied parameters if different from colon
 	 * for typeset -p output.
 	 */
-	unsigned char joinchar = STOUC(((struct tieddata *)peer->u.data)->joinchar);
+	unsigned char joinchar = (unsigned char) ((struct tieddata *)peer->u.data)->joinchar;
 	if (joinchar != ':') {
 	    char buf[2];
 	    buf[0] = joinchar;
diff --git a/Src/parse.c b/Src/parse.c
index 2fac5c89c..283225b74 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -433,9 +433,9 @@ ecstrcode(char *s)
 	t = has_token(s);
 	wordcode c = (t ? 3 : 2);
 	switch (l) {
-	case 4: c |= ((wordcode) STOUC(s[2])) << 19;
-	case 3: c |= ((wordcode) STOUC(s[1])) << 11;
-	case 2: c |= ((wordcode) STOUC(s[0])) <<  3; break;
+	case 4: c |= ((wordcode) (unsigned char) s[2]) << 19;
+	case 3: c |= ((wordcode) (unsigned char) s[1]) << 11;
+	case 2: c |= ((wordcode) (unsigned char) s[0]) <<  3; break;
 	case 1: c = (t ? 7 : 6); break;
 	}
 	return c;
diff --git a/Src/pattern.c b/Src/pattern.c
index e947d1216..3edda1772 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -239,7 +239,7 @@ typedef unsigned long zrange_t;
  * a bit tricky...
  */
 #define WCHAR_INVALID(ch)			\
-    ((wchar_t) (0xDC00 + STOUC(ch)))
+    ((wchar_t) (0xDC00 + (unsigned char) ch))
 #endif /* MULTIBYTE_SUPPORT */
 
 /*
@@ -346,7 +346,7 @@ metacharinc(char **x)
      * set doesn't have the property that all bytes with the 8th
      * bit clear are single characters then we are stuffed.
      */
-    if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(*inptr) & 0x80))
+    if (!(patglobflags & GF_MULTIBYTE) || !((unsigned char) *inptr & 0x80))
     {
 	if (itok(*inptr))
 	    inchar = ztokens[*inptr++ - Pound];
@@ -357,7 +357,7 @@ metacharinc(char **x)
 	    inchar = *inptr++;
 	}
 	*x = inptr;
-	return (wchar_t)STOUC(inchar);
+	return (wchar_t)(unsigned char) inchar;
     }
 
     while (*inptr) {
@@ -1181,8 +1181,8 @@ pattern_range_to_string(char *rangestr, char *outstr)
     int len = 0;
 
     while (*rangestr) {
-	if (imeta(STOUC(*rangestr))) {
-	    int swtype = STOUC(*rangestr) - STOUC(Meta);
+	if (imeta((unsigned char) *rangestr)) {
+	    int swtype = (unsigned char) *rangestr - (unsigned char) Meta;
 
 	    if (swtype == 0) {
 		/* Ordindary metafied character */
@@ -1278,17 +1278,17 @@ patcomppiece(int *flagp, int paren)
 	kshchar = '\0';
 	if (*patparse && patparse[1] == Inpar) {
 	    if (*patparse == zpc_special[ZPC_KSH_PLUS])
-		kshchar = STOUC('+');
+		kshchar = (unsigned char) '+';
 	    else if (*patparse == zpc_special[ZPC_KSH_BANG])
-		kshchar = STOUC('!');
+		kshchar = (unsigned char) '!';
 	    else if (*patparse == zpc_special[ZPC_KSH_BANG2])
-		kshchar = STOUC('!');
+		kshchar = (unsigned char) '!';
 	    else if (*patparse == zpc_special[ZPC_KSH_AT])
-		kshchar = STOUC('@');
+		kshchar = (unsigned char) '@';
 	    else if (*patparse == zpc_special[ZPC_KSH_STAR])
-		kshchar = STOUC('*');
+		kshchar = (unsigned char) '*';
 	    else if (*patparse == zpc_special[ZPC_KSH_QUEST])
-		kshchar = STOUC('?');
+		kshchar = (unsigned char) '?';
 	}
 
 	/*
@@ -1468,7 +1468,8 @@ patcomppiece(int *flagp, int paren)
 			ch = range_type(patparse, len);
 			patparse = nptr + 2;
 			if (ch != PP_UNKWN)
-			    patadd(NULL, STOUC(Meta) + ch, 1, PA_NOALIGN);
+			    patadd(NULL, (unsigned char) Meta + ch, 1,
+				PA_NOALIGN);
 			continue;
 		}
 		charstart = patparse;
@@ -1476,10 +1477,10 @@ patcomppiece(int *flagp, int paren)
 
 		if (*patparse == Dash && patparse[1] &&
 		    patparse[1] != Outbrack) {
-		    patadd(NULL, STOUC(Meta)+PP_RANGE, 1, PA_NOALIGN);
+		    patadd(NULL, (unsigned char) Meta+PP_RANGE, 1, PA_NOALIGN);
 		    if (itok(*charstart)) {
-			patadd(0, STOUC(ztokens[*charstart - Pound]), 1,
-			       PA_NOALIGN);
+			patadd(0, (unsigned char) ztokens[*charstart - Pound],
+			       1, PA_NOALIGN);
 		    } else {
 			patadd(charstart, 0, patparse-charstart, PA_NOALIGN);
 		    }
@@ -1487,7 +1488,7 @@ patcomppiece(int *flagp, int paren)
 		    METACHARINC(patparse);
 		}
 		if (itok(*charstart)) {
-		    patadd(0, STOUC(ztokens[*charstart - Pound]), 1,
+		    patadd(0, (unsigned char) ztokens[*charstart - Pound], 1,
 			   PA_NOALIGN);
 		} else {
 		    patadd(charstart, 0, patparse-charstart, PA_NOALIGN);
@@ -1910,8 +1911,8 @@ charref(char *x, char *y, int *zmb_ind)
     wchar_t wc;
     size_t ret;
 
-    if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(*x) & 0x80))
-	return (wchar_t) STOUC(*x);
+    if (!(patglobflags & GF_MULTIBYTE) || !((unsigned char) *x & 0x80))
+	return (wchar_t) (unsigned char) *x;
 
     ret = mbrtowc(&wc, x, y-x, &shiftstate);
 
@@ -1937,7 +1938,7 @@ charnext(char *x, char *y)
     wchar_t wc;
     size_t ret;
 
-    if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(*x) & 0x80))
+    if (!(patglobflags & GF_MULTIBYTE) || !((unsigned char) *x & 0x80))
 	return x + 1;
 
     ret = mbrtowc(&wc, x, y-x, &shiftstate);
@@ -1965,8 +1966,8 @@ charrefinc(char **x, char *y, int *z)
     wchar_t wc;
     size_t ret;
 
-    if (!(patglobflags & GF_MULTIBYTE) || !(STOUC(**x) & 0x80))
-	return (wchar_t) STOUC(*(*x)++);
+    if (!(patglobflags & GF_MULTIBYTE) || !((unsigned char) **x & 0x80))
+	return (wchar_t) (unsigned char) *(*x)++;
 
     ret = mbrtowc(&wc, *x, y-*x, &shiftstate);
 
@@ -2025,13 +2026,13 @@ charsub(char *x, char *y)
 #else /* no MULTIBYTE_SUPPORT */
 
 /* Get a character from the start point in a string */
-#define CHARREF(x, y)	(STOUC(*(x)))
+#define CHARREF(x, y)	((unsigned char) (*(x)))
 /* Get  a pointer to the next character */
 #define CHARNEXT(x, y)	((x)+1)
 /* Increment a pointer past the current character. */
 #define CHARINC(x, y)	((x)++)
 /* Get a character and increment */
-#define CHARREFINC(x, y, z)	(STOUC(*(x)++))
+#define CHARREFINC(x, y, z)	((unsigned char) (*(x)++))
 /* Counter the number of characters between two pointers, smaller first */
 #define CHARSUB(x,y)	((y) - (x))
 
@@ -2890,7 +2891,7 @@ patmatch(Upat prog)
 		}
 		if (!no && P_OP(next) == P_EXACTLY &&
 		    (!P_LS_LEN(next) ||
-		     !idigit(STOUC(*P_LS_STR(next)))) &&
+		     !idigit((unsigned char) (*P_LS_STR(next)))) &&
 		    !(patglobflags & 0xff))
 		    return 0;
 		patinput = --save;
@@ -3600,8 +3601,8 @@ mb_patmatchrange(char *range, wchar_t ch, int zmb_ind, wint_t *indptr, int *mtp)
      * ranges specially.
      */
     while (*range) {
-	if (imeta(STOUC(*range))) {
-	    int swtype = STOUC(*range++) - STOUC(Meta);
+	if (imeta((unsigned char) *range)) {
+	    int swtype = (unsigned char) *range++ - (unsigned char) Meta;
 	    if (mtp)
 		*mtp = swtype;
 	    switch (swtype) {
@@ -3753,8 +3754,8 @@ mb_patmatchindex(char *range, wint_t ind, wint_t *chr, int *mtp)
     *mtp = 0;
 
     while (*range) {
-	if (imeta(STOUC(*range))) {
-	    int swtype = STOUC(*range++) - STOUC(Meta);
+	if (imeta((unsigned char) *range)) {
+	    int swtype = (unsigned char) *range++ - (unsigned char) Meta;
 	    switch (swtype) {
 	    case 0:
 		range--;
@@ -3845,13 +3846,13 @@ patmatchrange(char *range, int ch, int *indptr, int *mtp)
      * ranges specially.
      */
     for (; *range; range++) {
-	if (imeta(STOUC(*range))) {
-	    int swtype = STOUC(*range) - STOUC(Meta);
+	if (imeta((unsigned char) *range)) {
+	    int swtype = (unsigned char) *range - (unsigned char) Meta;
 	    if (mtp)
 		*mtp = swtype;
 	    switch (swtype) {
 	    case 0:
-		if (STOUC(*++range ^ 32) == ch)
+		if ((unsigned char) (*++range ^ 32) == ch)
 		    return 1;
 		break;
 	    case PP_ALPHA:
@@ -3931,9 +3932,9 @@ patmatchrange(char *range, int ch, int *indptr, int *mtp)
 		break;
 	    case PP_RANGE:
 		range++;
-		r1 = STOUC(UNMETA(range));
+		r1 = (unsigned char) UNMETA(range);
 		METACHARINC(range);
-		r2 = STOUC(UNMETA(range));
+		r2 = (unsigned char) UNMETA(range);
 		if (*range == Meta)
 		    range++;
 		if (r1 <= ch && ch <= r2) {
@@ -3955,7 +3956,7 @@ patmatchrange(char *range, int ch, int *indptr, int *mtp)
 		DPUTS(1, "BUG: unknown metacharacter in range.");
 		break;
 	    }
-	} else if (STOUC(*range) == ch) {
+	} else if ((unsigned char) *range == ch) {
 	    if (mtp)
 		*mtp = 0;
 	    return 1;
@@ -3989,12 +3990,12 @@ patmatchindex(char *range, int ind, int *chr, int *mtp)
     *mtp = 0;
 
     for (; *range; range++) {
-	if (imeta(STOUC(*range))) {
-	    int swtype = STOUC(*range) - STOUC(Meta);
+	if (imeta((unsigned char) *range)) {
+	    int swtype = (unsigned char) *range - (unsigned char) Meta;
 	    switch (swtype) {
 	    case 0:
 		/* ordinary metafied character */
-		rchr = STOUC(*++range) ^ 32;
+		rchr = (unsigned char) *++range ^ 32;
 		if (!ind) {
 		    *chr = rchr;
 		    return 1;
@@ -4028,9 +4029,9 @@ patmatchindex(char *range, int ind, int *chr, int *mtp)
 
 	    case PP_RANGE:
 		range++;
-		r1 = STOUC(UNMETA(range));
+		r1 = (unsigned char) UNMETA(range);
 		METACHARINC(range);
-		r2 = STOUC(UNMETA(range));
+		r2 = (unsigned char) UNMETA(range);
 		if (*range == Meta)
 		    range++;
 		rdiff = r2 - r1; 
@@ -4050,7 +4051,7 @@ patmatchindex(char *range, int ind, int *chr, int *mtp)
 	    }
 	} else {
 	    if (!ind) {
-		*chr = STOUC(*range);
+		*chr = (unsigned char) *range;
 		return 1;
 	    }
 	}
diff --git a/Src/prompt.c b/Src/prompt.c
index 092de63a4..3cb95039c 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -1666,7 +1666,7 @@ match_colour(const char **teststrp, int is_fg, int colour)
 	tc = TCBGCOLOUR;
     }
     if (teststrp) {
-	if (**teststrp == '#' && isxdigit(STOUC((*teststrp)[1]))) {
+	if (**teststrp == '#' && isxdigit((unsigned char) (*teststrp)[1])) {
 	    struct color_rgb color;
 	    char *end;
 	    zlong col = zstrtol(*teststrp+1, &end, 16);
diff --git a/Src/sort.c b/Src/sort.c
index 26949ad9c..ce2b4bbc3 100644
--- a/Src/sort.c
+++ b/Src/sort.c
@@ -138,7 +138,7 @@ eltpcmp(const void *a, const void *b)
 	int mul = 0;
 	for (; *as == *bs && *as; as++, bs++);
 #ifndef HAVE_STRCOLL
-	cmp = (int)STOUC(*as) - (int)STOUC(*bs);
+	cmp = (int) (unsigned char) *as - (int) (unsigned char) *bs;
 #endif
 	if (sortnumeric < 0) {
 	    if (*as == '-' && idigit(as[1]) && idigit(*bs)) {
@@ -159,7 +159,7 @@ eltpcmp(const void *a, const void *b)
 		    bs++;
 		for (; idigit(*as) && *as == *bs; as++, bs++);
 		if (idigit(*as) || idigit(*bs)) {
-		    cmp = mul * ((int)STOUC(*as) - (int)STOUC(*bs));
+		    cmp = mul * ((int) (unsigned char) *as - (int) (unsigned char) *bs);
 		    while (idigit(*as) && idigit(*bs))
 			as++, bs++;
 		    if (idigit(*as) && !idigit(*bs))
diff --git a/Src/subst.c b/Src/subst.c
index 0f98e6ea3..b8e4023e1 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -556,7 +556,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep,
 	for ( ; *x; x += l) {
 	    char c = (l = *x == Meta) ? x[1] ^ 32 : *x;
 	    l++;
-	    if (!iwsep(STOUC(c)))
+	    if (!iwsep((unsigned char) c))
 		break;
 	    *ms_flags |= MULTSUB_WS_AT_START;
 	}
@@ -573,7 +573,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep,
 	    convchar_t c;
 	    if (*x == Dash)
 		*x = '-';
-	    if (itok(STOUC(*x))) {
+	    if (itok((unsigned char) *x)) {
 		/* token, can't be separator, must be single byte */
 		rawc = *x;
 		l = 1;
@@ -582,7 +582,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep,
 		if (!inq && !inp && WC_ZISTYPE(c, ISEP)) {
 		    *x = '\0';
 		    for (x += l; *x; x += l) {
-			if (itok(STOUC(*x))) {
+			if (itok((unsigned char) *x)) {
 			    /* as above */
 			    rawc = *x;
 			    l = 1;
diff --git a/Src/utils.c b/Src/utils.c
index edf5d3df7..32492a93b 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -86,7 +86,7 @@ set_widearray(char *mb_array, Widechar_array wca)
 	while (*mb_array) {
 	    int mblen;
 
-	    if (STOUC(*mb_array) <= 0x7f) {
+	    if ((unsigned char) *mb_array <= 0x7f) {
 		mb_array++;
 		*wcptr++ = (wchar_t)*mb_array;
 		continue;
@@ -2920,7 +2920,7 @@ read1char(int echo)
     restore_queue_signals(q);
     if (echo)
 	write_loop(SHTTY, &c, 1);
-    return STOUC(c);
+    return (unsigned char) c;
 }
 
 /**/
@@ -4123,20 +4123,20 @@ inittyptab(void)
 #endif
     /* typtab['.'] |= IIDENT; */ /* Allow '.' in variable names - broken */
     typtab['_'] = IIDENT | IUSER;
-    typtab['-'] = typtab['.'] = typtab[STOUC(Dash)] = IUSER;
+    typtab['-'] = typtab['.'] = typtab[(unsigned char) Dash] = IUSER;
     typtab[' '] |= IBLANK | INBLANK;
     typtab['\t'] |= IBLANK | INBLANK;
     typtab['\n'] |= INBLANK;
     typtab['\0'] |= IMETA;
-    typtab[STOUC(Meta)  ] |= IMETA;
-    typtab[STOUC(Marker)] |= IMETA;
-    for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(LAST_NORMAL_TOK); t0++)
+    typtab[(unsigned char) Meta  ] |= IMETA;
+    typtab[(unsigned char) Marker] |= IMETA;
+    for (t0 = (int) (unsigned char) Pound; t0 <= (int) (unsigned char) LAST_NORMAL_TOK; t0++)
 	typtab[t0] |= ITOK | IMETA;
-    for (t0 = (int)STOUC(Snull); t0 <= (int)STOUC(Nularg); t0++)
+    for (t0 = (int) (unsigned char) Snull; t0 <= (int) (unsigned char) Nularg; t0++)
 	typtab[t0] |= ITOK | IMETA | INULL;
     for (s = ifs ? ifs : EMULATION(EMULATE_KSH|EMULATE_SH) ?
 	DEFAULT_IFS_SH : DEFAULT_IFS; *s; s++) {
-	int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
+	int c = (unsigned char) (*s == Meta ? *++s ^ 32 : *s);
 #ifdef MULTIBYTE_SUPPORT
 	if (!isascii(c)) {
 	    /* see comment for wordchars below */
@@ -4152,7 +4152,7 @@ inittyptab(void)
 	typtab[c] |= ISEP;
     }
     for (s = wordchars ? wordchars : DEFAULT_WORDCHARS; *s; s++) {
-	int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
+	int c = (unsigned char) (*s == Meta ? *++s ^ 32 : *s);
 #ifdef MULTIBYTE_SUPPORT
 	if (!isascii(c)) {
 	    /*
@@ -4173,16 +4173,16 @@ inittyptab(void)
 	DEFAULT_IFS_SH : DEFAULT_IFS, &ifs_wide);
 #endif
     for (s = SPECCHARS; *s; s++)
-	typtab[STOUC(*s)] |= ISPECIAL;
+	typtab[(unsigned char) *s] |= ISPECIAL;
     if (typtab_flags & ZTF_SP_COMMA)
-	typtab[STOUC(',')] |= ISPECIAL;
+	typtab[(unsigned char) ','] |= ISPECIAL;
     if (isset(BANGHIST) && bangchar && (typtab_flags & ZTF_INTERACT)) {
 	typtab_flags |= ZTF_BANGCHAR;
 	typtab[bangchar] |= ISPECIAL;
     } else
 	typtab_flags &= ~ZTF_BANGCHAR;
     for (s = PATCHARS; *s; s++)
-	typtab[STOUC(*s)] |= IPATTERN;
+	typtab[(unsigned char) *s] |= IPATTERN;
 
     unqueue_signals();
 }
@@ -4193,10 +4193,10 @@ makecommaspecial(int yesno)
 {
     if (yesno != 0) {
 	typtab_flags |= ZTF_SP_COMMA;
-	typtab[STOUC(',')] |= ISPECIAL;
+	typtab[(unsigned char) ','] |= ISPECIAL;
     } else {
 	typtab_flags &= ~ZTF_SP_COMMA;
-	typtab[STOUC(',')] &= ~ISPECIAL;
+	typtab[(unsigned char) ','] &= ~ISPECIAL;
     }
 }
 
@@ -4336,7 +4336,7 @@ itype_end(const char *ptr, int itype, int once)
 
 		if (wc == WEOF) {
 		    /* invalid, treat as single character */
-		    int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
+		    int chr = (unsigned char) (*ptr == Meta ? ptr[1] ^ 32 : *ptr);
 		    /* in this case non-ASCII characters can't match */
 		    if (chr > 127 || !zistype(chr,itype))
 			break;
@@ -4375,7 +4375,7 @@ itype_end(const char *ptr, int itype, int once)
     } else
 #endif
 	for (;;) {
-	    int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
+	    int chr = (unsigned char) (*ptr == Meta ? ptr[1] ^ 32 : *ptr);
 	    if (!zistype(chr,itype))
 		break;
 	    ptr += (*ptr == Meta) ? 2 : 1;
@@ -4983,11 +4983,11 @@ unmeta_one(const char *in, int *sz)
     *sz = mb_metacharlenconv_r(in, &wc, &wstate);
 #else
     if (in[0] == Meta) {
-      *sz = 2;
-      wc = STOUC(in[1] ^ 32);
+	*sz = 2;
+	wc = (unsigned char) (in[1] ^ 32);
     } else {
-      *sz = 1;
-      wc = STOUC(in[0]);
+	*sz = 1;
+	wc = (unsigned char) in[0];
     }
 #endif
     return wc;
@@ -5022,11 +5022,11 @@ ztrcmp(char const *s1, char const *s2)
 
     if(!(c1 = *s1))
 	c1 = -1;
-    else if(c1 == STOUC(Meta))
+    else if(c1 == (unsigned char) Meta)
 	c1 = *++s1 ^ 32;
     if(!(c2 = *s2))
 	c2 = -1;
-    else if(c2 == STOUC(Meta))
+    else if(c2 == (unsigned char) Meta)
 	c2 = *++s2 ^ 32;
 
     if(c1 == c2)
@@ -5458,7 +5458,7 @@ mb_metacharlenconv_r(const char *s, wint_t *wcp, mbstate_t *mbsp)
     const char *ptr;
     wchar_t wc;
 
-    if (STOUC(*s) <= 0x7f) {
+    if ((unsigned char) *s <= 0x7f) {
 	if (wcp)
 	    *wcp = (wint_t)*s;
 	return 1;
@@ -5516,10 +5516,10 @@ mb_metacharlenconv_r(const char *s, wint_t *wcp, mbstate_t *mbsp)
 mod_export int
 mb_metacharlenconv(const char *s, wint_t *wcp)
 {
-    if (!isset(MULTIBYTE) || STOUC(*s) <= 0x7f) {
+    if (!isset(MULTIBYTE) || (unsigned char) *s <= 0x7f) {
 	/* treat as single byte, possibly metafied */
 	if (wcp)
-	    *wcp = (wint_t)STOUC(*s == Meta ? s[1] ^ 32 : *s);
+	    *wcp = (wint_t)(unsigned char) (*s == Meta ? s[1] ^ 32 : *s);
 	return 1 + (*s == Meta);
     }
     /*
@@ -5581,7 +5581,7 @@ mb_metastrlenend(char *ptr, int width, char *eptr)
 	    inchar = *ptr;
 	ptr++;
 
-	if (complete && STOUC(inchar) <= STOUC(0x7f)) {
+	if (complete && (unsigned char) inchar <= (unsigned char) 0x7f) {
 	    /*
 	     * We rely on 7-bit US-ASCII as a subset, so skip
 	     * multibyte handling if we have such a character.
@@ -5657,7 +5657,7 @@ mb_charlenconv_r(const char *s, int slen, wint_t *wcp, mbstate_t *mbsp)
     const char *ptr;
     wchar_t wc;
 
-    if (slen && STOUC(*s) <= 0x7f) {
+    if (slen && (unsigned char) *s <= 0x7f) {
 	if (wcp)
 	    *wcp = (wint_t)*s;
 	return 1;
@@ -5698,7 +5698,7 @@ mb_charlenconv_r(const char *s, int slen, wint_t *wcp, mbstate_t *mbsp)
 mod_export int
 mb_charlenconv(const char *s, int slen, wint_t *wcp)
 {
-    if (!isset(MULTIBYTE) || STOUC(*s) <= 0x7f) {
+    if (!isset(MULTIBYTE) || (unsigned char) *s <= 0x7f) {
 	if (wcp)
 	    *wcp = (wint_t)*s;
 	return 1;
@@ -5717,7 +5717,7 @@ mod_export int
 metacharlenconv(const char *x, int *c)
 {
     /*
-     * Here we don't use STOUC() on the chars since they
+     * Here we don't use an (unsigned char)  cast on the chars since they
      * may be compared against other chars and this will fail
      * if chars are signed and the high bit is set.
      */
@@ -5779,7 +5779,7 @@ sb_niceformat(const char *s, FILE *stream, char **outstrp, int flags)
     eptr = ptr + umlen;
 
     while (ptr < eptr) {
-	int c = STOUC(*ptr);
+	int c = (unsigned char) *ptr;
 	if (c == '\'' && (flags & NICEFLAG_QUOTE)) {
 	    fmt = "\\'";
 	    newl = 2;
@@ -5996,9 +5996,9 @@ addunprintable(char *v, const char *u, const char *uend)
 	 */
 	int c;
 	if (*u == Meta)
-	    c = STOUC(*++u ^ 32);
+	    c = (unsigned char) (*++u ^ 32);
 	else
-	    c = STOUC(*u);
+	    c = (unsigned char) *u;
 	switch (c) {
 	case '\0':
 	    *v++ = '\\';
@@ -7104,7 +7104,7 @@ getkeystring(char *s, int *len, int how, int *misc)
 	    continue;
 #ifdef MULTIBYTE_SUPPORT
 	} else if ((how & GETKEY_SINGLE_CHAR) &&
-		   isset(MULTIBYTE) && STOUC(*s) > 127) {
+		   isset(MULTIBYTE) && (unsigned char) *s > 127) {
 	    wint_t wc;
 	    int len;
 	    len = mb_metacharlenconv(s, &wc);
@@ -7207,7 +7207,7 @@ getkeystring(char *s, int *len, int how, int *misc)
 	    t = tbuf;
 	}
 	if ((how & GETKEY_SINGLE_CHAR) && t != tmp) {
-	    *misc = STOUC(tmp[0]);
+	    *misc = (unsigned char) tmp[0];
 	    return s + 1;
 	}
     }
diff --git a/Src/zsh.h b/Src/zsh.h
index 703231ca2..a59340184 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -135,19 +135,6 @@ struct mathfunc {
 #define STRMATHFUNC(name, func, id) \
     { NULL, name, MFF_STR, NULL, func, NULL, 0, 0, id }
 
-/* Character tokens are sometimes casted to (unsigned char)'s.         * 
- * Unfortunately, some compilers don't correctly cast signed to        * 
- * unsigned promotions; i.e. (int)(unsigned char)((char) -1) evaluates * 
- * to -1, instead of 255 like it should.  We circumvent the troubles   * 
- * of such shameful delinquency by casting to a larger unsigned type   * 
- * then back down to unsigned char.                                    */
-
-#ifdef BROKEN_SIGNED_TO_UNSIGNED_CASTING
-# define STOUC(X)	((unsigned char)(unsigned short)(X))
-#else
-# define STOUC(X)	((unsigned char)(X))
-#endif
-
 /* Meta together with the character following Meta denotes the character *
  * which is the exclusive or of 32 and the character following Meta.     *
  * This is used to represent characters which otherwise has special      *
diff --git a/Src/ztype.h b/Src/ztype.h
index 5c85b0cd7..8757fc733 100644
--- a/Src/ztype.h
+++ b/Src/ztype.h
@@ -43,7 +43,7 @@
 #define IWSEP    (1 << 13)
 #define INULL    (1 << 14)
 #define IPATTERN (1 << 15)
-#define zistype(X,Y) (typtab[STOUC(X)] & Y)
+#define zistype(X,Y) (typtab[(unsigned char) (X)] & Y)
 #define idigit(X) zistype(X,IDIGIT)
 #define ialnum(X) zistype(X,IALNUM)
 #define iblank(X) zistype(X,IBLANK)	/* blank, not including \n */
diff --git a/configure.ac b/configure.ac
index 074141d38..f340d2993 100644
--- a/configure.ac
+++ b/configure.ac
@@ -582,16 +582,6 @@ if test x$zsh_cv_c_have_union_init = xyes; then
   AC_DEFINE(HAVE_UNION_INIT)
 fi
 
-dnl  Checking if compiler correctly cast signed to unsigned.
-AC_CACHE_CHECK(if signed to unsigned casting is broken,
-zsh_cv_c_broken_signed_to_unsigned_casting,
-[AC_RUN_IFELSE([AC_LANG_SOURCE([[int main(){return((int)(unsigned char)((char) -1) == 255);}]])],[zsh_cv_c_broken_signed_to_unsigned_casting=yes],[zsh_cv_c_broken_signed_to_unsigned_casting=no],[zsh_cv_c_broken_signed_to_unsigned_casting=no])])
-AH_TEMPLATE([BROKEN_SIGNED_TO_UNSIGNED_CASTING],
-[Define to 1 if compiler incorrectly cast signed to unsigned.])
-if test x$zsh_cv_c_broken_signed_to_unsigned_casting = xyes; then
-  AC_DEFINE(BROKEN_SIGNED_TO_UNSIGNED_CASTING)
-fi
-
 dnl Checking if the compiler supports variable-length arrays
 AC_CACHE_CHECK(if the compiler supports variable-length arrays,
 zsh_cv_c_variable_length_arrays,


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: PATCH: remove ancient STOUC() workaround
  2022-12-14 16:52 PATCH: remove ancient STOUC() workaround Oliver Kiddle
@ 2022-12-14 17:07 ` Peter Stephenson
  0 siblings, 0 replies; 2+ messages in thread
From: Peter Stephenson @ 2022-12-14 17:07 UTC (permalink / raw)
  To: Zsh workers

> On 14/12/2022 16:52 Oliver Kiddle <opk@zsh.org> wrote:
> The STOUC() macro is a wrapper for (unsigned char) casts that works
> around a compiler bug by doing ((unsigned char)(unsigned short)(X)) if
> autoconf detects the bug. This has been there since before the earliest
> (1995) list archives. I've never come across the need for this in any
> other C codebase. Surely whatever compiler needed this has long since
> ceased to be able to compile zsh for a myriad other reasons and been
> confined to a museum. A web search for the autoconf output of "signed to
> unsigned casting is broken..." finds matches with the word "no" but none
> with "yes". Or is there some further need for this that I'm missing?

I would imagine you're right and it's well past its shelf life.  The only
way to know with this ancient stuff is to suck it and see.

pws


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-12-14 17:07 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-14 16:52 PATCH: remove ancient STOUC() workaround Oliver Kiddle
2022-12-14 17:07 ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).