Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / unescape.c
blob94a46ae7e023c148123e5ee9a6e1b0e7086494b3
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* unescape 3
6 /* SUMMARY
7 /* translate C-like escape sequences
8 /* SYNOPSIS
9 /* #include <stringops.h>
11 /* VSTRING *unescape(result, input)
12 /* VSTRING *result;
13 /* const char *input;
15 /* VSTRING *escape(result, input, len)
16 /* VSTRING *result;
17 /* const char *input;
18 /* ssize_t len;
19 /* DESCRIPTION
20 /* unescape() translates C-like escape sequences in the null-terminated
21 /* string \fIinput\fR and places the result in \fIresult\fR. The result
22 /* is null-terminated, and is the function result value.
24 /* escape() does the reverse transformation.
26 /* Escape sequences and their translations:
27 /* .IP \ea
28 /* Bell character.
29 /* .IP \eb
30 /* Backspace character.
31 /* .IP \ef
32 /* formfeed character.
33 /* .IP \en
34 /* newline character
35 /* .IP \er
36 /* Carriage-return character.
37 /* .IP \et
38 /* Horizontal tab character.
39 /* .IP \ev
40 /* Vertical tab character.
41 /* .IP \e\e
42 /* Backslash character.
43 /* .IP \e\fInum\fR
44 /* 8-bit character whose ASCII value is the 1..3 digit
45 /* octal number \fInum\fR.
46 /* .IP \e\fIother\fR
47 /* The backslash character is discarded.
48 /* LICENSE
49 /* .ad
50 /* .fi
51 /* The Secure Mailer license must be distributed with this software.
52 /* AUTHOR(S)
53 /* Wietse Venema
54 /* IBM T.J. Watson Research
55 /* P.O. Box 704
56 /* Yorktown Heights, NY 10598, USA
57 /*--*/
59 /* System library. */
61 #include <sys_defs.h>
62 #include <ctype.h>
64 /* Utility library. */
66 #include <vstring.h>
67 #include <stringops.h>
69 /* unescape - process escape sequences */
71 VSTRING *unescape(VSTRING *result, const char *data)
73 int ch;
74 int oval;
75 int i;
77 #define UCHAR(cp) ((unsigned char *) (cp))
78 #define ISOCTAL(ch) (ISDIGIT(ch) && (ch) != '8' && (ch) != '9')
80 VSTRING_RESET(result);
82 while ((ch = *UCHAR(data++)) != 0) {
83 if (ch == '\\') {
84 if ((ch = *UCHAR(data++)) == 0)
85 break;
86 switch (ch) {
87 case 'a': /* \a -> audible bell */
88 ch = '\a';
89 break;
90 case 'b': /* \b -> backspace */
91 ch = '\b';
92 break;
93 case 'f': /* \f -> formfeed */
94 ch = '\f';
95 break;
96 case 'n': /* \n -> newline */
97 ch = '\n';
98 break;
99 case 'r': /* \r -> carriagereturn */
100 ch = '\r';
101 break;
102 case 't': /* \t -> horizontal tab */
103 ch = '\t';
104 break;
105 case 'v': /* \v -> vertical tab */
106 ch = '\v';
107 break;
108 case '0': /* \nnn -> ASCII value */
109 case '1':
110 case '2':
111 case '3':
112 case '4':
113 case '5':
114 case '6':
115 case '7':
116 for (oval = ch - '0', i = 0;
117 i < 2 && (ch = *UCHAR(data)) != 0 && ISOCTAL(ch);
118 i++, data++) {
119 oval = (oval << 3) | (ch - '0');
121 ch = oval;
122 break;
123 default: /* \any -> any */
124 break;
127 VSTRING_ADDCH(result, ch);
129 VSTRING_TERMINATE(result);
130 return (result);
133 /* escape - reverse transformation */
135 VSTRING *escape(VSTRING *result, const char *data, ssize_t len)
137 int ch;
139 VSTRING_RESET(result);
140 while (len-- > 0) {
141 ch = *UCHAR(data++);
142 if (ISASCII(ch)) {
143 if (ISPRINT(ch)) {
144 if (ch == '\\')
145 VSTRING_ADDCH(result, ch);
146 VSTRING_ADDCH(result, ch);
147 continue;
148 } else if (ch == '\a') { /* \a -> audible bell */
149 vstring_strcat(result, "\\a");
150 continue;
151 } else if (ch == '\b') { /* \b -> backspace */
152 vstring_strcat(result, "\\b");
153 continue;
154 } else if (ch == '\f') { /* \f -> formfeed */
155 vstring_strcat(result, "\\f");
156 continue;
157 } else if (ch == '\n') { /* \n -> newline */
158 vstring_strcat(result, "\\n");
159 continue;
160 } else if (ch == '\r') { /* \r -> carriagereturn */
161 vstring_strcat(result, "\\r");
162 continue;
163 } else if (ch == '\t') { /* \t -> horizontal tab */
164 vstring_strcat(result, "\\t");
165 continue;
166 } else if (ch == '\v') { /* \v -> vertical tab */
167 vstring_strcat(result, "\\v");
168 continue;
171 if (ISDIGIT(*UCHAR(data)))
172 vstring_sprintf_append(result, "\\%03d", ch);
173 else
174 vstring_sprintf_append(result, "\\%d", ch);
176 VSTRING_TERMINATE(result);
177 return (result);
180 #ifdef TEST
182 #include <stdlib.h>
183 #include <string.h>
184 #include <msg.h>
185 #include <vstring_vstream.h>
187 int main(int argc, char **argv)
189 VSTRING *in = vstring_alloc(10);
190 VSTRING *out = vstring_alloc(10);
191 int un_escape = 1;
193 if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0)
194 msg_fatal("usage: %s [-e (escape)]", argv[0]);
196 if (un_escape) {
197 while (vstring_fgets_nonl(in, VSTREAM_IN)) {
198 unescape(out, vstring_str(in));
199 vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
201 } else {
202 while (vstring_fgets(in, VSTREAM_IN)) {
203 escape(out, vstring_str(in), VSTRING_LEN(in));
204 vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
207 vstream_fflush(VSTREAM_OUT);
208 exit(0);
211 #endif