* escapes(): escape expansion for showsyms. C-style escapes understood * include \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). * (Note: unlike in C, leading digit 0 is not used to indicate octal; * the letter o (either upper or lower case) is used for that. * The ^-prefix for control characters is also understood, and \[mM] * has the effect of 'meta'-ing the value which follows
| 6893 | * or 'O', plus stop if the non-digit is end-of-string. |
| 6894 | */ |
| 6895 | staticfn void |
| 6896 | escapes(const char *cp, /* might be 'tp', updating in place */ |
| 6897 | char *tp) /* result is never longer than 'cp' */ |
| 6898 | { |
| 6899 | static NEARDATA const char oct[] = "01234567", dec[] = "0123456789"; |
| 6900 | /* hexdd[] is defined in decl.c */ |
| 6901 | |
| 6902 | const char *dp; |
| 6903 | int cval, meta, dcount; |
| 6904 | |
| 6905 | while (*cp) { |
| 6906 | /* \M has to be followed by something to do meta conversion, |
| 6907 | otherwise it will just be \M which ultimately yields 'M' */ |
| 6908 | meta = (*cp == '\\' && (cp[1] == 'm' || cp[1] == 'M') && cp[2]); |
| 6909 | if (meta) |
| 6910 | cp += 2; |
| 6911 | |
| 6912 | cval = dcount = 0; /* for decimal, octal, hexadecimal cases */ |
| 6913 | if ((*cp != '\\' && *cp != '^') || !cp[1]) { |
| 6914 | /* simple character, or nothing left for \ or ^ to escape */ |
| 6915 | cval = *cp++; |
| 6916 | } else if (*cp == '^') { /* expand control-character syntax */ |
| 6917 | cval = (*++cp & 0x1f); |
| 6918 | ++cp; |
| 6919 | |
| 6920 | /* remaining cases are all for backslash; we know cp[1] is not \0 */ |
| 6921 | } else if (strchr(dec, cp[1])) { |
| 6922 | ++cp; /* move past backslash to first digit */ |
| 6923 | do { |
| 6924 | cval = (cval * 10) + (*cp - '0'); |
| 6925 | } while (*++cp && strchr(dec, *cp) && ++dcount < 3); |
| 6926 | } else if ((cp[1] == 'o' || cp[1] == 'O') && cp[2] |
| 6927 | && strchr(oct, cp[2])) { |
| 6928 | cp += 2; /* move past backslash and 'O' */ |
| 6929 | do { |
| 6930 | cval = (cval * 8) + (*cp - '0'); |
| 6931 | } while (*++cp && strchr(oct, *cp) && ++dcount < 3); |
| 6932 | } else if ((cp[1] == 'x' || cp[1] == 'X') && cp[2] |
| 6933 | && (dp = strchr(hexdd, cp[2])) != 0) { |
| 6934 | cp += 2; /* move past backslash and 'X' */ |
| 6935 | do { |
| 6936 | cval = (cval * 16) + ((int) (dp - hexdd) / 2); |
| 6937 | } while (*++cp && (dp = strchr(hexdd, *cp)) != 0 && ++dcount < 2); |
| 6938 | } else { /* C-style character escapes */ |
| 6939 | switch (*++cp) { |
| 6940 | case '\\': |
| 6941 | cval = '\\'; |
| 6942 | break; |
| 6943 | case 'n': |
| 6944 | cval = '\n'; |
| 6945 | break; |
| 6946 | case 't': |
| 6947 | cval = '\t'; |
| 6948 | break; |
| 6949 | case 'b': |
| 6950 | cval = '\b'; |
| 6951 | break; |
| 6952 | case 'r': |
no outgoing calls
no test coverage detected