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