conv.c revision 1.14 1 1.14 lukem /* $NetBSD: conv.c,v 1.14 2001/11/26 00:13:23 lukem 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.7 christos #include <sys/cdefs.h>
41 1.1 glass #ifndef lint
42 1.4 cgd #if 0
43 1.4 cgd static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
44 1.4 cgd #else
45 1.14 lukem __RCSID("$NetBSD: conv.c,v 1.14 2001/11/26 00:13:23 lukem Exp $");
46 1.4 cgd #endif
47 1.1 glass #endif /* not lint */
48 1.1 glass
49 1.1 glass #include <sys/param.h>
50 1.11 ross #include <sys/time.h>
51 1.1 glass
52 1.3 mycroft #include <err.h>
53 1.1 glass #include <string.h>
54 1.1 glass
55 1.1 glass #include "dd.h"
56 1.1 glass #include "extern.h"
57 1.1 glass
58 1.1 glass /*
59 1.1 glass * def --
60 1.1 glass * Copy input to output. Input is buffered until reaches obs, and then
61 1.1 glass * output until less than obs remains. Only a single buffer is used.
62 1.1 glass * Worst case buffer calculation is (ibs + obs - 1).
63 1.1 glass */
64 1.1 glass void
65 1.12 lukem def(void)
66 1.1 glass {
67 1.14 lukem uint64_t cnt;
68 1.6 jtc u_char *inp;
69 1.6 jtc const u_char *t;
70 1.1 glass
71 1.7 christos if ((t = ctab) != NULL)
72 1.1 glass for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
73 1.1 glass *inp = t[*inp];
74 1.1 glass
75 1.1 glass /* Make the output buffer look right. */
76 1.1 glass out.dbp = in.dbp;
77 1.1 glass out.dbcnt = in.dbcnt;
78 1.1 glass
79 1.1 glass if (in.dbcnt >= out.dbsz) {
80 1.1 glass /* If the output buffer is full, write it. */
81 1.1 glass dd_out(0);
82 1.1 glass
83 1.1 glass /*
84 1.1 glass * Ddout copies the leftover output to the beginning of
85 1.1 glass * the buffer and resets the output buffer. Reset the
86 1.1 glass * input buffer to match it.
87 1.1 glass */
88 1.1 glass in.dbp = out.dbp;
89 1.1 glass in.dbcnt = out.dbcnt;
90 1.1 glass }
91 1.1 glass }
92 1.1 glass
93 1.1 glass void
94 1.12 lukem def_close(void)
95 1.1 glass {
96 1.12 lukem
97 1.1 glass /* Just update the count, everything is already in the buffer. */
98 1.1 glass if (in.dbcnt)
99 1.1 glass out.dbcnt = in.dbcnt;
100 1.1 glass }
101 1.1 glass
102 1.5 gwr #ifdef NO_CONV
103 1.5 gwr /* Build a smaller version (i.e. for a miniroot) */
104 1.5 gwr /* These can not be called, but just in case... */
105 1.12 lukem static const char no_block[] = "unblock and -DNO_CONV?";
106 1.12 lukem void block(void) { errx(1, "%s", no_block + 2); }
107 1.12 lukem void block_close(void) { errx(1, "%s", no_block + 2); }
108 1.12 lukem void unblock(void) { errx(1, "%s", no_block); }
109 1.12 lukem void unblock_close(void) { errx(1, "%s", no_block); }
110 1.5 gwr #else /* NO_CONV */
111 1.5 gwr
112 1.1 glass /*
113 1.1 glass * Copy variable length newline terminated records with a max size cbsz
114 1.1 glass * bytes to output. Records less than cbs are padded with spaces.
115 1.1 glass *
116 1.1 glass * max in buffer: MAX(ibs, cbsz)
117 1.1 glass * max out buffer: obs + cbsz
118 1.1 glass */
119 1.1 glass void
120 1.12 lukem block(void)
121 1.1 glass {
122 1.1 glass static int intrunc;
123 1.7 christos int ch = 0; /* pacify gcc */
124 1.14 lukem uint64_t cnt, maxlen;
125 1.6 jtc u_char *inp, *outp;
126 1.6 jtc const u_char *t;
127 1.1 glass
128 1.1 glass /*
129 1.1 glass * Record truncation can cross block boundaries. If currently in a
130 1.1 glass * truncation state, keep tossing characters until reach a newline.
131 1.1 glass * Start at the beginning of the buffer, as the input buffer is always
132 1.1 glass * left empty.
133 1.1 glass */
134 1.1 glass if (intrunc) {
135 1.1 glass for (inp = in.db, cnt = in.dbrcnt;
136 1.1 glass cnt && *inp++ != '\n'; --cnt);
137 1.1 glass if (!cnt) {
138 1.1 glass in.dbcnt = 0;
139 1.1 glass in.dbp = in.db;
140 1.1 glass return;
141 1.1 glass }
142 1.1 glass intrunc = 0;
143 1.1 glass /* Adjust the input buffer numbers. */
144 1.1 glass in.dbcnt = cnt - 1;
145 1.1 glass in.dbp = inp + cnt - 1;
146 1.1 glass }
147 1.1 glass
148 1.1 glass /*
149 1.1 glass * Copy records (max cbsz size chunks) into the output buffer. The
150 1.1 glass * translation is done as we copy into the output buffer.
151 1.1 glass */
152 1.1 glass for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
153 1.1 glass maxlen = MIN(cbsz, in.dbcnt);
154 1.7 christos if ((t = ctab) != NULL)
155 1.1 glass for (cnt = 0;
156 1.1 glass cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
157 1.1 glass *outp++ = t[ch];
158 1.1 glass else
159 1.1 glass for (cnt = 0;
160 1.1 glass cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
161 1.1 glass *outp++ = ch;
162 1.1 glass /*
163 1.1 glass * Check for short record without a newline. Reassemble the
164 1.1 glass * input block.
165 1.1 glass */
166 1.1 glass if (ch != '\n' && in.dbcnt < cbsz) {
167 1.8 mycroft (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
168 1.1 glass break;
169 1.1 glass }
170 1.1 glass
171 1.1 glass /* Adjust the input buffer numbers. */
172 1.1 glass in.dbcnt -= cnt;
173 1.1 glass if (ch == '\n')
174 1.1 glass --in.dbcnt;
175 1.1 glass
176 1.1 glass /* Pad short records with spaces. */
177 1.1 glass if (cnt < cbsz)
178 1.1 glass (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
179 1.1 glass else {
180 1.1 glass /*
181 1.1 glass * If the next character wouldn't have ended the
182 1.1 glass * block, it's a truncation.
183 1.1 glass */
184 1.1 glass if (!in.dbcnt || *inp != '\n')
185 1.1 glass ++st.trunc;
186 1.1 glass
187 1.1 glass /* Toss characters to a newline. */
188 1.1 glass for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt);
189 1.1 glass if (!in.dbcnt)
190 1.1 glass intrunc = 1;
191 1.1 glass else
192 1.1 glass --in.dbcnt;
193 1.1 glass }
194 1.1 glass
195 1.1 glass /* Adjust output buffer numbers. */
196 1.1 glass out.dbp += cbsz;
197 1.1 glass if ((out.dbcnt += cbsz) >= out.dbsz)
198 1.1 glass dd_out(0);
199 1.1 glass outp = out.dbp;
200 1.1 glass }
201 1.1 glass in.dbp = in.db + in.dbcnt;
202 1.1 glass }
203 1.1 glass
204 1.1 glass void
205 1.12 lukem block_close(void)
206 1.1 glass {
207 1.12 lukem
208 1.1 glass /*
209 1.1 glass * Copy any remaining data into the output buffer and pad to a record.
210 1.1 glass * Don't worry about truncation or translation, the input buffer is
211 1.1 glass * always empty when truncating, and no characters have been added for
212 1.1 glass * translation. The bottom line is that anything left in the input
213 1.1 glass * buffer is a truncated record. Anything left in the output buffer
214 1.1 glass * just wasn't big enough.
215 1.1 glass */
216 1.1 glass if (in.dbcnt) {
217 1.1 glass ++st.trunc;
218 1.8 mycroft (void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
219 1.1 glass (void)memset(out.dbp + in.dbcnt,
220 1.1 glass ctab ? ctab[' '] : ' ', cbsz - in.dbcnt);
221 1.1 glass out.dbcnt += cbsz;
222 1.1 glass }
223 1.1 glass }
224 1.1 glass
225 1.1 glass /*
226 1.1 glass * Convert fixed length (cbsz) records to variable length. Deletes any
227 1.1 glass * trailing blanks and appends a newline.
228 1.1 glass *
229 1.1 glass * max in buffer: MAX(ibs, cbsz) + cbsz
230 1.1 glass * max out buffer: obs + cbsz
231 1.1 glass */
232 1.1 glass void
233 1.12 lukem unblock(void)
234 1.1 glass {
235 1.14 lukem uint64_t cnt;
236 1.6 jtc u_char *inp;
237 1.6 jtc const u_char *t;
238 1.1 glass
239 1.1 glass /* Translation and case conversion. */
240 1.7 christos if ((t = ctab) != NULL)
241 1.10 cgd for (cnt = in.dbrcnt, inp = in.dbp - 1; cnt--; inp--)
242 1.10 cgd *inp = t[*inp];
243 1.1 glass /*
244 1.1 glass * Copy records (max cbsz size chunks) into the output buffer. The
245 1.1 glass * translation has to already be done or we might not recognize the
246 1.1 glass * spaces.
247 1.1 glass */
248 1.1 glass for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
249 1.1 glass for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t);
250 1.1 glass if (t >= inp) {
251 1.1 glass cnt = t - inp + 1;
252 1.8 mycroft (void)memmove(out.dbp, inp, cnt);
253 1.1 glass out.dbp += cnt;
254 1.1 glass out.dbcnt += cnt;
255 1.1 glass }
256 1.1 glass ++out.dbcnt;
257 1.1 glass *out.dbp++ = '\n';
258 1.1 glass if (out.dbcnt >= out.dbsz)
259 1.1 glass dd_out(0);
260 1.1 glass }
261 1.1 glass if (in.dbcnt)
262 1.8 mycroft (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
263 1.1 glass in.dbp = in.db + in.dbcnt;
264 1.1 glass }
265 1.1 glass
266 1.1 glass void
267 1.12 lukem unblock_close(void)
268 1.1 glass {
269 1.14 lukem uint64_t cnt;
270 1.3 mycroft u_char *t;
271 1.1 glass
272 1.1 glass if (in.dbcnt) {
273 1.3 mycroft warnx("%s: short input record", in.name);
274 1.1 glass for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t);
275 1.1 glass if (t >= in.db) {
276 1.1 glass cnt = t - in.db + 1;
277 1.8 mycroft (void)memmove(out.dbp, in.db, cnt);
278 1.1 glass out.dbp += cnt;
279 1.1 glass out.dbcnt += cnt;
280 1.1 glass }
281 1.1 glass ++out.dbcnt;
282 1.1 glass *out.dbp++ = '\n';
283 1.1 glass }
284 1.1 glass }
285 1.5 gwr
286 1.5 gwr #endif /* NO_CONV */
287