xref: /plan9/sys/src/cmd/gs/src/sbcp.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1993, 2000 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: sbcp.c,v 1.5 2002/02/21 22:24:53 giles Exp $ */
18 /* BCP and TBCP filters */
19 #include "stdio_.h"
20 #include "strimpl.h"
21 #include "sbcp.h"
22 
23 #define CtrlA 0x01
24 #define CtrlC 0x03
25 #define CtrlD 0x04
26 #define CtrlE 0x05
27 #define CtrlQ 0x11
28 #define CtrlS 0x13
29 #define CtrlT 0x14
30 #define ESC 0x1b
31 #define CtrlBksl 0x1c
32 
33 /* The following is not used yet. */
34 /*private const char *TBCP_end_protocol_string = "\033%-12345X"; */
35 
36 /* ------ BCPEncode and TBCPEncode ------ */
37 
38 /* Process a buffer */
39 private int
s_xBCPE_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last,const byte * escaped)40 s_xBCPE_process(stream_state * st, stream_cursor_read * pr,
41 		stream_cursor_write * pw, bool last, const byte * escaped)
42 {
43     const byte *p = pr->ptr;
44     const byte *rlimit = pr->limit;
45     uint rcount = rlimit - p;
46     byte *q = pw->ptr;
47     uint wcount = pw->limit - q;
48     const byte *end = p + min(rcount, wcount);
49 
50     while (p < end) {
51 	byte ch = *++p;
52 
53 	if (ch <= 31 && escaped[ch]) {
54 	    if (p == rlimit) {
55 		p--;
56 		break;
57 	    }
58 	    *++q = CtrlA;
59 	    ch ^= 0x40;
60 	    if (--wcount < rcount)
61 		end--;
62 	}
63 	*++q = ch;
64     }
65     pr->ptr = p;
66     pw->ptr = q;
67     return (p == rlimit ? 0 : 1);
68 }
69 
70 /* Actual process procedures */
71 private int
s_BCPE_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)72 s_BCPE_process(stream_state * st, stream_cursor_read * pr,
73 	       stream_cursor_write * pw, bool last)
74 {
75     static const byte escaped[32] =
76     {
77 	0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 	0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
79     };
80 
81     return s_xBCPE_process(st, pr, pw, last, escaped);
82 }
83 private int
s_TBCPE_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)84 s_TBCPE_process(stream_state * st, stream_cursor_read * pr,
85 		stream_cursor_write * pw, bool last)
86 {
87     static const byte escaped[32] =
88     {
89 	0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90 	0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0
91     };
92 
93     return s_xBCPE_process(st, pr, pw, last, escaped);
94 }
95 
96 /* Stream templates */
97 const stream_template s_BCPE_template =
98 {&st_stream_state, NULL, s_BCPE_process, 1, 2
99 };
100 const stream_template s_TBCPE_template =
101 {&st_stream_state, NULL, s_TBCPE_process, 1, 2
102 };
103 
104 /* ------ BCPDecode and TBCPDecode ------ */
105 
106 private_st_BCPD_state();
107 
108 /* Initialize the state */
109 private int
s_BCPD_init(stream_state * st)110 s_BCPD_init(stream_state * st)
111 {
112     stream_BCPD_state *const ss = (stream_BCPD_state *) st;
113 
114     ss->escaped = 0;
115     ss->matched = ss->copy_count = 0;
116     return 0;
117 }
118 
119 /* Process a buffer */
120 private int
s_xBCPD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last,bool tagged)121 s_xBCPD_process(stream_state * st, stream_cursor_read * pr,
122 		stream_cursor_write * pw, bool last, bool tagged)
123 {
124     stream_BCPD_state *const ss = (stream_BCPD_state *) st;
125     const byte *p = pr->ptr;
126     const byte *rlimit = pr->limit;
127     byte *q = pw->ptr;
128     byte *wlimit = pw->limit;
129     int copy_count = ss->copy_count;
130     int status;
131     bool escaped = ss->escaped;
132 
133     for (;;) {
134 	byte ch;
135 
136 	if (copy_count) {
137 	    if (q == wlimit) {
138 		status = (p < rlimit ? 1 : 0);
139 		break;
140 	    }
141 	    *++q = *++(ss->copy_ptr);
142 	    copy_count--;
143 	    continue;
144 	}
145 	if (p == rlimit) {
146 	    status = 0;
147 	    break;
148 	}
149 	ch = *++p;
150 	if (ch <= 31)
151 	    switch (ch) {
152 		case CtrlA:
153 		    if (escaped) {
154 			status = ERRC;
155 			goto out;
156 		    }
157 		    escaped = true;
158 		    continue;
159 		case CtrlC:
160 		    status = (*ss->signal_interrupt) (st);
161 		    if (status < 0)
162 			goto out;
163 		    continue;
164 		case CtrlD:
165 		    if (escaped) {
166 			status = ERRC;
167 			goto out;
168 		    }
169 		    status = EOFC;
170 		    goto out;
171 		case CtrlE:
172 		    continue;
173 		case CtrlQ:
174 		    continue;
175 		case CtrlS:
176 		    continue;
177 		case CtrlT:
178 		    status = (*ss->request_status) (st);
179 		    if (status < 0)
180 			goto out;
181 		    continue;
182 		case CtrlBksl:
183 		    continue;
184 	    }
185 	if (q == wlimit) {
186 	    p--;
187 	    status = 1;
188 	    break;
189 	}
190 	if (escaped) {
191 	    escaped = false;
192 	    switch (ch) {
193 		case '[':
194 		    if (!tagged) {
195 			status = ERRC;
196 			goto out;
197 		    }
198 		    /* falls through */
199 		case 'A':
200 		case 'C':
201 		case 'D':
202 		case 'E':
203 		case 'Q':
204 		case 'S':
205 		case 'T':
206 		case '\\':
207 		    ch ^= 0x40;
208 		    break;
209 		case 'M':
210 		    if (!tagged) {
211 			status = ERRC;
212 			goto out;
213 		    }
214 		    continue;
215 		default:
216 		    status = ERRC;
217 		    goto out;
218 	    }
219 	}
220 	*++q = ch;
221     }
222   out:ss->copy_count = copy_count;
223     ss->escaped = escaped;
224     pr->ptr = p;
225     pw->ptr = q;
226     return status;
227 }
228 
229 /* Actual process procedures */
230 private int
s_BCPD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)231 s_BCPD_process(stream_state * st, stream_cursor_read * pr,
232 	       stream_cursor_write * pw, bool last)
233 {
234     return s_xBCPD_process(st, pr, pw, last, false);
235 }
236 private int
s_TBCPD_process(stream_state * st,stream_cursor_read * pr,stream_cursor_write * pw,bool last)237 s_TBCPD_process(stream_state * st, stream_cursor_read * pr,
238 		stream_cursor_write * pw, bool last)
239 {
240     return s_xBCPD_process(st, pr, pw, last, true);
241 }
242 
243 /* Stream templates */
244 const stream_template s_BCPD_template =
245 {&st_BCPD_state, s_BCPD_init, s_BCPD_process, 1, 1,
246  NULL, NULL, s_BCPD_init
247 };
248 const stream_template s_TBCPD_template =
249 {&st_BCPD_state, s_BCPD_init, s_TBCPD_process, 1, 1,
250  NULL, NULL, s_BCPD_init
251 };
252