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