}
/*
- * escapes: escape expansion for showsyms. C-style escapes understood include
- * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix
- * for control characters is also understood, and \[mM] followed by any of the
- * previous forms or by a character has the effect of 'meta'-ing the value (so
- * that the alternate character set will be enabled).
+ * escapes(): escape expansion for showsyms. C-style escapes understood
+ * include \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal).
+ * The ^-prefix for control characters is also understood, and \[mM]
+ * 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.
*/
STATIC_OVL void
escapes(cp, tp)
const char *cp;
char *tp;
{
- while (*cp)
- {
+ while (*cp) {
int cval = 0, meta = 0;
- if (*cp == '\\' && index("mM", cp[1])) {
+ if (*cp == '\\' && cp[1] && index("mM", cp[1]) && cp[2]) {
meta = 1;
cp += 2;
}
- if (*cp == '\\' && index("0123456789xXoO", cp[1]))
- {
- const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
+ 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 = (int)((cval * 16) + (dp - hex) / 2);
+ 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 == '\\') /* C-style character escapes */
- {
- switch (*++cp)
- {
+ } else if (*cp == '\\' && cp[1]) { /* C-style character escapes */
+ switch (*++cp) {
case '\\': cval = '\\'; break;
case 'n': cval = '\n'; break;
case 't': cval = '\t'; break;
default: cval = *cp;
}
cp++;
- }
- else if (*cp == '^') /* expand control-character syntax */
- {
+ } else if (*cp == '^' && cp[1]) { /* expand control-character syntax */
cval = (*++cp & 0x1f);
cp++;
- }
- else
+ } else
cval = *cp++;
+
if (meta)
cval |= 0x80;
*tp++ = cval;