conv.c revision 1.5 1 1.5 gwr /* $NetBSD: conv.c,v 1.5 1995/10/08 23:01:23 gwr Exp $ */
2 1.4 cgd
3 1.1 glass /*-
4 1.3 mycroft * Copyright (c) 1991, 1993, 1994
5 1.3 mycroft * The Regents of the University of California. All rights reserved.
6 1.1 glass *
7 1.1 glass * This code is derived from software contributed to Berkeley by
8 1.1 glass * Keith Muller of the University of California, San Diego and Lance
9 1.1 glass * Visser of Convex Computer Corporation.
10 1.1 glass *
11 1.1 glass * Redistribution and use in source and binary forms, with or without
12 1.1 glass * modification, are permitted provided that the following conditions
13 1.1 glass * are met:
14 1.1 glass * 1. Redistributions of source code must retain the above copyright
15 1.1 glass * notice, this list of conditions and the following disclaimer.
16 1.1 glass * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 glass * notice, this list of conditions and the following disclaimer in the
18 1.1 glass * documentation and/or other materials provided with the distribution.
19 1.1 glass * 3. All advertising materials mentioning features or use of this software
20 1.1 glass * must display the following acknowledgement:
21 1.1 glass * This product includes software developed by the University of
22 1.1 glass * California, Berkeley and its contributors.
23 1.1 glass * 4. Neither the name of the University nor the names of its contributors
24 1.1 glass * may be used to endorse or promote products derived from this software
25 1.1 glass * without specific prior written permission.
26 1.1 glass *
27 1.1 glass * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 1.1 glass * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 1.1 glass * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 1.1 glass * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 1.1 glass * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 1.1 glass * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 1.1 glass * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 1.1 glass * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 1.1 glass * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 1.1 glass * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 1.1 glass * SUCH DAMAGE.
38 1.1 glass */
39 1.1 glass
40 1.1 glass #ifndef lint
41 1.4 cgd #if 0
42 1.4 cgd static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
43 1.4 cgd #else
44 1.5 gwr static char rcsid[] = "$NetBSD: conv.c,v 1.5 1995/10/08 23:01:23 gwr Exp $";
45 1.4 cgd #endif
46 1.1 glass #endif /* not lint */
47 1.1 glass
48 1.1 glass #include <sys/param.h>
49 1.1 glass
50 1.3 mycroft #include <err.h>
51 1.1 glass #include <string.h>
52 1.1 glass
53 1.1 glass #include "dd.h"
54 1.1 glass #include "extern.h"
55 1.1 glass
56 1.1 glass /*
57 1.1 glass * def --
58 1.1 glass * Copy input to output. Input is buffered until reaches obs, and then
59 1.1 glass * output until less than obs remains. Only a single buffer is used.
60 1.1 glass * Worst case buffer calculation is (ibs + obs - 1).
61 1.1 glass */
62 1.1 glass void
63 1.1 glass def()
64 1.1 glass {
65 1.3 mycroft int cnt;
66 1.3 mycroft u_char *inp, *t;
67 1.1 glass
68 1.1 glass if (t = ctab)
69 1.1 glass for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
70 1.1 glass *inp = t[*inp];
71 1.1 glass
72 1.1 glass /* Make the output buffer look right. */
73 1.1 glass out.dbp = in.dbp;
74 1.1 glass out.dbcnt = in.dbcnt;
75 1.1 glass
76 1.1 glass if (in.dbcnt >= out.dbsz) {
77 1.1 glass /* If the output buffer is full, write it. */
78 1.1 glass dd_out(0);
79 1.1 glass
80 1.1 glass /*
81 1.1 glass * Ddout copies the leftover output to the beginning of
82 1.1 glass * the buffer and resets the output buffer. Reset the
83 1.1 glass * input buffer to match it.
84 1.1 glass */
85 1.1 glass in.dbp = out.dbp;
86 1.1 glass in.dbcnt = out.dbcnt;
87 1.1 glass }
88 1.1 glass }
89 1.1 glass
90 1.1 glass void
91 1.1 glass def_close()
92 1.1 glass {
93 1.1 glass /* Just update the count, everything is already in the buffer. */
94 1.1 glass if (in.dbcnt)
95 1.1 glass out.dbcnt = in.dbcnt;
96 1.1 glass }
97 1.1 glass
98 1.5 gwr #ifdef NO_CONV
99 1.5 gwr /* Build a smaller version (i.e. for a miniroot) */
100 1.5 gwr /* These can not be called, but just in case... */
101 1.5 gwr static char no_block[] = "unblock and -DNO_CONV?";
102 1.5 gwr void block() { errx(1, no_block + 2); }
103 1.5 gwr void block_close() { errx(1, no_block + 2); }
104 1.5 gwr void unblock() { errx(1, no_block); }
105 1.5 gwr void unblock_close() { errx(1, no_block); }
106 1.5 gwr #else /* NO_CONV */
107 1.5 gwr
108 1.1 glass /*
109 1.1 glass * Copy variable length newline terminated records with a max size cbsz
110 1.1 glass * bytes to output. Records less than cbs are padded with spaces.
111 1.1 glass *
112 1.1 glass * max in buffer: MAX(ibs, cbsz)
113 1.1 glass * max out buffer: obs + cbsz
114 1.1 glass */
115 1.1 glass void
116 1.1 glass block()
117 1.1 glass {
118 1.1 glass static int intrunc;
119 1.3 mycroft int ch, cnt, maxlen;
120 1.3 mycroft u_char *inp, *outp, *t;
121 1.1 glass
122 1.1 glass /*
123 1.1 glass * Record truncation can cross block boundaries. If currently in a
124 1.1 glass * truncation state, keep tossing characters until reach a newline.
125 1.1 glass * Start at the beginning of the buffer, as the input buffer is always
126 1.1 glass * left empty.
127 1.1 glass */
128 1.1 glass if (intrunc) {
129 1.1 glass for (inp = in.db, cnt = in.dbrcnt;
130 1.1 glass cnt && *inp++ != '\n'; --cnt);
131 1.1 glass if (!cnt) {
132 1.1 glass in.dbcnt = 0;
133 1.1 glass in.dbp = in.db;
134 1.1 glass return;
135 1.1 glass }
136 1.1 glass intrunc = 0;
137 1.1 glass /* Adjust the input buffer numbers. */
138 1.1 glass in.dbcnt = cnt - 1;
139 1.1 glass in.dbp = inp + cnt - 1;
140 1.1 glass }
141 1.1 glass
142 1.1 glass /*
143 1.1 glass * Copy records (max cbsz size chunks) into the output buffer. The
144 1.1 glass * translation is done as we copy into the output buffer.
145 1.1 glass */
146 1.1 glass for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
147 1.1 glass maxlen = MIN(cbsz, in.dbcnt);
148 1.1 glass if (t = ctab)
149 1.1 glass for (cnt = 0;
150 1.1 glass cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
151 1.1 glass *outp++ = t[ch];
152 1.1 glass else
153 1.1 glass for (cnt = 0;
154 1.1 glass cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
155 1.1 glass *outp++ = ch;
156 1.1 glass /*
157 1.1 glass * Check for short record without a newline. Reassemble the
158 1.1 glass * input block.
159 1.1 glass */
160 1.1 glass if (ch != '\n' && in.dbcnt < cbsz) {
161 1.1 glass memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
162 1.1 glass break;
163 1.1 glass }
164 1.1 glass
165 1.1 glass /* Adjust the input buffer numbers. */
166 1.1 glass in.dbcnt -= cnt;
167 1.1 glass if (ch == '\n')
168 1.1 glass --in.dbcnt;
169 1.1 glass
170 1.1 glass /* Pad short records with spaces. */
171 1.1 glass if (cnt < cbsz)
172 1.1 glass (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
173 1.1 glass else {
174 1.1 glass /*
175 1.1 glass * If the next character wouldn't have ended the
176 1.1 glass * block, it's a truncation.
177 1.1 glass */
178 1.1 glass if (!in.dbcnt || *inp != '\n')
179 1.1 glass ++st.trunc;
180 1.1 glass
181 1.1 glass /* Toss characters to a newline. */
182 1.1 glass for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt);
183 1.1 glass if (!in.dbcnt)
184 1.1 glass intrunc = 1;
185 1.1 glass else
186 1.1 glass --in.dbcnt;
187 1.1 glass }
188 1.1 glass
189 1.1 glass /* Adjust output buffer numbers. */
190 1.1 glass out.dbp += cbsz;
191 1.1 glass if ((out.dbcnt += cbsz) >= out.dbsz)
192 1.1 glass dd_out(0);
193 1.1 glass outp = out.dbp;
194 1.1 glass }
195 1.1 glass in.dbp = in.db + in.dbcnt;
196 1.1 glass }
197 1.1 glass
198 1.1 glass void
199 1.1 glass block_close()
200 1.1 glass {
201 1.1 glass /*
202 1.1 glass * Copy any remaining data into the output buffer and pad to a record.
203 1.1 glass * Don't worry about truncation or translation, the input buffer is
204 1.1 glass * always empty when truncating, and no characters have been added for
205 1.1 glass * translation. The bottom line is that anything left in the input
206 1.1 glass * buffer is a truncated record. Anything left in the output buffer
207 1.1 glass * just wasn't big enough.
208 1.1 glass */
209 1.1 glass if (in.dbcnt) {
210 1.1 glass ++st.trunc;
211 1.1 glass memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
212 1.1 glass (void)memset(out.dbp + in.dbcnt,
213 1.1 glass ctab ? ctab[' '] : ' ', cbsz - in.dbcnt);
214 1.1 glass out.dbcnt += cbsz;
215 1.1 glass }
216 1.1 glass }
217 1.1 glass
218 1.1 glass /*
219 1.1 glass * Convert fixed length (cbsz) records to variable length. Deletes any
220 1.1 glass * trailing blanks and appends a newline.
221 1.1 glass *
222 1.1 glass * max in buffer: MAX(ibs, cbsz) + cbsz
223 1.1 glass * max out buffer: obs + cbsz
224 1.1 glass */
225 1.1 glass void
226 1.1 glass unblock()
227 1.1 glass {
228 1.3 mycroft int cnt;
229 1.3 mycroft u_char *inp, *t;
230 1.1 glass
231 1.1 glass /* Translation and case conversion. */
232 1.1 glass if (t = ctab)
233 1.1 glass for (cnt = in.dbrcnt, inp = in.dbp; cnt--;)
234 1.1 glass *--inp = t[*inp];
235 1.1 glass /*
236 1.1 glass * Copy records (max cbsz size chunks) into the output buffer. The
237 1.1 glass * translation has to already be done or we might not recognize the
238 1.1 glass * spaces.
239 1.1 glass */
240 1.1 glass for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
241 1.1 glass for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t);
242 1.1 glass if (t >= inp) {
243 1.1 glass cnt = t - inp + 1;
244 1.1 glass memmove(out.dbp, inp, cnt);
245 1.1 glass out.dbp += cnt;
246 1.1 glass out.dbcnt += cnt;
247 1.1 glass }
248 1.1 glass ++out.dbcnt;
249 1.1 glass *out.dbp++ = '\n';
250 1.1 glass if (out.dbcnt >= out.dbsz)
251 1.1 glass dd_out(0);
252 1.1 glass }
253 1.1 glass if (in.dbcnt)
254 1.1 glass memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
255 1.1 glass in.dbp = in.db + in.dbcnt;
256 1.1 glass }
257 1.1 glass
258 1.1 glass void
259 1.1 glass unblock_close()
260 1.1 glass {
261 1.3 mycroft int cnt;
262 1.3 mycroft u_char *t;
263 1.1 glass
264 1.1 glass if (in.dbcnt) {
265 1.3 mycroft warnx("%s: short input record", in.name);
266 1.1 glass for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t);
267 1.1 glass if (t >= in.db) {
268 1.1 glass cnt = t - in.db + 1;
269 1.1 glass memmove(out.dbp, in.db, cnt);
270 1.1 glass out.dbp += cnt;
271 1.1 glass out.dbcnt += cnt;
272 1.1 glass }
273 1.1 glass ++out.dbcnt;
274 1.1 glass *out.dbp++ = '\n';
275 1.1 glass }
276 1.1 glass }
277 1.5 gwr
278 1.5 gwr #endif /* NO_CONV */
279