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