/*++ /* NAME /* unescape 3 /* SUMMARY /* translate C-like escape sequences /* SYNOPSIS /* #include /* /* VSTRING *unescape(result, input) /* VSTRING *result; /* const char *input; /* /* VSTRING *escape(result, input, len) /* VSTRING *result; /* const char *input; /* ssize_t len; /* DESCRIPTION /* unescape() translates C-like escape sequences in the null-terminated /* string \fIinput\fR and places the result in \fIresult\fR. The result /* is null-terminated, and is the function result value. /* /* escape() does the reverse transformation. /* /* Escape sequences and their translations: /* .IP \ea /* Bell character. /* .IP \eb /* Backspace character. /* .IP \ef /* formfeed character. /* .IP \en /* newline character /* .IP \er /* Carriage-return character. /* .IP \et /* Horizontal tab character. /* .IP \ev /* Vertical tab character. /* .IP \e\e /* Backslash character. /* .IP \e\fInum\fR /* 8-bit character whose ASCII value is the 1..3 digit /* octal number \fInum\fR. /* .IP \e\fIother\fR /* The backslash character is discarded. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include #include /* Utility library. */ #include #include /* unescape - process escape sequences */ VSTRING *unescape(VSTRING *result, const char *data) { int ch; int oval; int i; #define UCHAR(cp) ((unsigned char *) (cp)) #define ISOCTAL(ch) (ISDIGIT(ch) && (ch) != '8' && (ch) != '9') VSTRING_RESET(result); while ((ch = *UCHAR(data++)) != 0) { if (ch == '\\') { if ((ch = *UCHAR(data++)) == 0) break; switch (ch) { case 'a': /* \a -> audible bell */ ch = '\a'; break; case 'b': /* \b -> backspace */ ch = '\b'; break; case 'f': /* \f -> formfeed */ ch = '\f'; break; case 'n': /* \n -> newline */ ch = '\n'; break; case 'r': /* \r -> carriagereturn */ ch = '\r'; break; case 't': /* \t -> horizontal tab */ ch = '\t'; break; case 'v': /* \v -> vertical tab */ ch = '\v'; break; case '0': /* \nnn -> ASCII value */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': for (oval = ch - '0', i = 0; i < 2 && (ch = *UCHAR(data)) != 0 && ISOCTAL(ch); i++, data++) { oval = (oval << 3) | (ch - '0'); } ch = oval; break; default: /* \any -> any */ break; } } VSTRING_ADDCH(result, ch); } VSTRING_TERMINATE(result); return (result); } /* escape - reverse transformation */ VSTRING *escape(VSTRING *result, const char *data, ssize_t len) { int ch; VSTRING_RESET(result); while (len-- > 0) { ch = *UCHAR(data++); if (ISASCII(ch)) { if (ISPRINT(ch)) { if (ch == '\\') VSTRING_ADDCH(result, ch); VSTRING_ADDCH(result, ch); continue; } else if (ch == '\a') { /* \a -> audible bell */ vstring_strcat(result, "\\a"); continue; } else if (ch == '\b') { /* \b -> backspace */ vstring_strcat(result, "\\b"); continue; } else if (ch == '\f') { /* \f -> formfeed */ vstring_strcat(result, "\\f"); continue; } else if (ch == '\n') { /* \n -> newline */ vstring_strcat(result, "\\n"); continue; } else if (ch == '\r') { /* \r -> carriagereturn */ vstring_strcat(result, "\\r"); continue; } else if (ch == '\t') { /* \t -> horizontal tab */ vstring_strcat(result, "\\t"); continue; } else if (ch == '\v') { /* \v -> vertical tab */ vstring_strcat(result, "\\v"); continue; } } vstring_sprintf_append(result, "\\%03o", ch); } VSTRING_TERMINATE(result); return (result); } #ifdef TEST #include #include #include #include int main(int argc, char **argv) { VSTRING *in = vstring_alloc(10); VSTRING *out = vstring_alloc(10); int un_escape = 1; if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0) msg_fatal("usage: %s [-e (escape)]", argv[0]); if (un_escape) { while (vstring_fgets_nonl(in, VSTREAM_IN)) { unescape(out, vstring_str(in)); vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out)); VSTREAM_PUTC('\n', VSTREAM_OUT); } } else { while (vstring_fgets_nonl(in, VSTREAM_IN)) { escape(out, vstring_str(in), VSTRING_LEN(in)); vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out)); VSTREAM_PUTC('\n', VSTREAM_OUT); } } vstream_fflush(VSTREAM_OUT); exit(0); } #endif