From: nethack.rankin Date: Thu, 4 Aug 2011 02:41:44 +0000 (+0000) Subject: escapes() revamp X-Git-Tag: MOVE2GIT~190 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=612755bfb5c412079795c68ba392df5d93874ed8;p=nethack escapes() revamp Partial rewrite of escapes(), mostly changing its if-then-else logic so that end-of-string can be checked once instead for each case. The previous version had a bug if the input string ended with backslash and one decimal digit (due to being lumped together with the handling for trailing \X or \O). --- diff --git a/src/options.c b/src/options.c index c4a696aa0..49911f0f4 100644 --- a/src/options.c +++ b/src/options.c @@ -753,40 +753,58 @@ nmcpy(dest, src, maxlen) * has the effect of 'meta'-ing the value which follows (so that the * alternate character set will be enabled). * - * For 3.4.3 and earlier, ending with "\M", backslash, or caret prior - * to terminating '\0' would pull that '\0' into the output and then - * keep processing past it. Now, a trailing escape will be handled - * as if it was preceded with its own backslash and be kept as is, - * with end of string terminator always honored as end of input. + * For 3.4.3 and earlier, input ending with "\M", backslash, or caret + * prior to terminating '\0' would pull that '\0' into the output and then + * keep processing past it, potentially overflowing the output buffer. + * Now, trailing \ or ^ will act like \\ or \^ and add '\\' or '^' to the + * output and stop there; trailing \M will fall through to \ and + * yield 'M', then stop. Any \X or \O followed by something other than + * an appropriate digit will also fall through to \ and yield 'X' + * or 'O', plus stop if the non-digit is end-of-string. */ STATIC_OVL void escapes(cp, tp) const char *cp; char *tp; { + static NEARDATA const char + oct[] = "01234567", dec[] = "0123456789", + hex[] = "00112233445566778899aAbBcCdDeEfF"; + const char *dp; + int cval, meta, dcount; + while (*cp) { - int cval = 0, meta = 0; - - if (*cp == '\\' && cp[1] && index("mM", cp[1]) && cp[2]) { - meta = 1; - cp += 2; - } - if (*cp == '\\' && cp[1] && index("0123456789xXoO", cp[1]) && cp[2]) { - NEARDATA const char hex[] = "00112233445566778899aAbBcCdDeEfF"; - const char *dp; - int dcount = 0; - - cp++; - if (*cp == 'x' || *cp == 'X') - for (++cp; *cp && (dp = index(hex, *cp)) && (dcount++ < 2); cp++) - cval = (cval * 16) + ((int)(dp - hex) / 2); - else if (*cp == 'o' || *cp == 'O') - for (++cp; *cp && (index("01234567",*cp)) && (dcount++ < 3); cp++) - cval = (cval * 8) + (*cp - '0'); - else - for (; *cp && (index("0123456789",*cp)) && (dcount++ < 3); cp++) - cval = (cval * 10) + (*cp - '0'); - } else if (*cp == '\\' && cp[1]) { /* C-style character escapes */ + /* \M has to be followed by something to do meta conversion, + otherwise it will just be \M which ultimately yields 'M' */ + meta = (*cp == '\\' && (cp[1] == 'm' || cp[1] == 'M') && cp[2]); + if (meta) cp += 2; + + cval = dcount = 0; /* for decimal, octal, hexadecimal cases */ + if ((*cp != '\\' && *cp != '^') || !cp[1]) { + /* simple character, or nothing left for \ or ^ to escape */ + cval = *cp++; + } else if (*cp == '^') { /* expand control-character syntax */ + cval = (*++cp & 0x1f); + ++cp; + /* remaining cases are all for backslash and we know cp[1] is not \0 */ + } else if (index(dec, cp[1])) { + ++cp; /* move past backslash to first digit */ + do { + cval = (cval * 10) + (*cp - '0'); + } while (*++cp && index(dec, *cp) && ++dcount < 3); + } else if ((cp[1] == 'o' || cp[1] == 'O') && + cp[2] && index(oct, cp[2])) { + cp += 2; /* move past backslash and 'O' */ + do { + cval = (cval * 8) + (*cp - '0'); + } while (*++cp && index(oct, *cp) && ++dcount < 3); + } else if ((cp[1] == 'x' || cp[1] == 'X') && + cp[2] && (dp = index(hex, cp[2])) != 0) { + cp += 2; /* move past backslash and 'X' */ + do { + cval = (cval * 16) + ((int)(dp - hex) / 2); + } while (*++cp && (dp = index(hex, *cp)) != 0 && ++dcount < 2); + } else { /* C-style character escapes */ switch (*++cp) { case '\\': cval = '\\'; break; case 'n': cval = '\n'; break; @@ -795,16 +813,12 @@ char *tp; case 'r': cval = '\r'; break; default: cval = *cp; } - cp++; - } else if (*cp == '^' && cp[1]) { /* expand control-character syntax */ - cval = (*++cp & 0x1f); - cp++; - } else - cval = *cp++; + ++cp; + } if (meta) cval |= 0x80; - *tp++ = cval; + *tp++ = (char)cval; } *tp = '\0'; }