conv.c revision 19720
150276Speter/*- 2174993Srafan * Copyright (c) 1991, 1993, 1994 350276Speter * The Regents of the University of California. All rights reserved. 450276Speter * 550276Speter * This code is derived from software contributed to Berkeley by 650276Speter * Keith Muller of the University of California, San Diego and Lance 750276Speter * Visser of Convex Computer Corporation. 850276Speter * 950276Speter * Redistribution and use in source and binary forms, with or without 1050276Speter * modification, are permitted provided that the following conditions 1150276Speter * are met: 1250276Speter * 1. Redistributions of source code must retain the above copyright 1350276Speter * notice, this list of conditions and the following disclaimer. 1450276Speter * 2. Redistributions in binary form must reproduce the above copyright 1550276Speter * notice, this list of conditions and the following disclaimer in the 1650276Speter * documentation and/or other materials provided with the distribution. 1750276Speter * 3. All advertising materials mentioning features or use of this software 1850276Speter * must display the following acknowledgement: 1950276Speter * This product includes software developed by the University of 2050276Speter * California, Berkeley and its contributors. 2150276Speter * 4. Neither the name of the University nor the names of its contributors 2250276Speter * may be used to endorse or promote products derived from this software 2350276Speter * without specific prior written permission. 2450276Speter * 2550276Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2650276Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2750276Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2850276Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2950276Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30166124Srafan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3150276Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3250276Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3350276Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3450276Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35174993Srafan * SUCH DAMAGE. 3650276Speter * 37166124Srafan * $Id: conv.c,v 1.4 1996/11/12 23:09:04 phk Exp $ 38166124Srafan */ 39166124Srafan 40166124Srafan#ifndef lint 41174993Srafanstatic char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94"; 42166124Srafan#endif /* not lint */ 43166124Srafan 44166124Srafan#include <sys/param.h> 45166124Srafan 4650276Speter#include <err.h> 47166124Srafan#include <string.h> 48166124Srafan 49166124Srafan#include "dd.h" 50166124Srafan#include "extern.h" 51166124Srafan 52166124Srafan/* 53166124Srafan * def -- 54166124Srafan * Copy input to output. Input is buffered until reaches obs, and then 55166124Srafan * output until less than obs remains. Only a single buffer is used. 56166124Srafan * Worst case buffer calculation is (ibs + obs - 1). 57174993Srafan */ 58174993Srafanvoid 59166124Srafandef() 60166124Srafan{ 61166124Srafan int cnt; 62166124Srafan u_char *inp, *t; 63166124Srafan 64166124Srafan if ((t = ctab) != NULL) 65166124Srafan for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp) 66166124Srafan *inp = t[*inp]; 67166124Srafan 68166124Srafan /* Make the output buffer look right. */ 69166124Srafan out.dbp = in.dbp; 70166124Srafan out.dbcnt = in.dbcnt; 71166124Srafan 72166124Srafan if (in.dbcnt >= out.dbsz) { 73166124Srafan /* If the output buffer is full, write it. */ 74166124Srafan dd_out(0); 75166124Srafan 76166124Srafan /* 77166124Srafan * Ddout copies the leftover output to the beginning of 78166124Srafan * the buffer and resets the output buffer. Reset the 79166124Srafan * input buffer to match it. 80174993Srafan */ 81166124Srafan in.dbp = out.dbp; 82166124Srafan in.dbcnt = out.dbcnt; 83166124Srafan } 8450276Speter} 8550276Speter 8650276Spetervoid 8750276Speterdef_close() 8876726Speter{ 8950276Speter /* Just update the count, everything is already in the buffer. */ 9050276Speter if (in.dbcnt) 91166124Srafan out.dbcnt = in.dbcnt; 9262449Speter} 93166124Srafan 9450276Speter/* 9550276Speter * Copy variable length newline terminated records with a max size cbsz 9662449Speter * bytes to output. Records less than cbs are padded with spaces. 9762449Speter * 98166124Srafan * max in buffer: MAX(ibs, cbsz) 99166124Srafan * max out buffer: obs + cbsz 100166124Srafan */ 101166124Srafanvoid 102174993Srafanblock() 10350276Speter{ 104174993Srafan static int intrunc; 105174993Srafan int ch, cnt, maxlen; 10662449Speter u_char *inp, *outp, *t; 10750276Speter 10850276Speter /* 10962449Speter * Record truncation can cross block boundaries. If currently in a 11062449Speter * truncation state, keep tossing characters until reach a newline. 11150276Speter * Start at the beginning of the buffer, as the input buffer is always 11262449Speter * left empty. 11362449Speter */ 11450276Speter if (intrunc) { 11562449Speter for (inp = in.db, cnt = in.dbrcnt; 11662449Speter cnt && *inp++ != '\n'; --cnt); 11762449Speter if (!cnt) { 11850276Speter in.dbcnt = 0; 11962449Speter in.dbp = in.db; 12050276Speter return; 12162449Speter } 12262449Speter intrunc = 0; 12362449Speter /* Adjust the input buffer numbers. */ 12450276Speter in.dbcnt = cnt - 1; 12562449Speter in.dbp = inp + cnt - 1; 12662449Speter } 12762449Speter 12862449Speter /* 12962449Speter * Copy records (max cbsz size chunks) into the output buffer. The 13062449Speter * translation is done as we copy into the output buffer. 13162449Speter */ 13262449Speter ch = 0; /* Help the compiler. */ 13350276Speter for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) { 13462449Speter maxlen = MIN(cbsz, in.dbcnt); 135166124Srafan if ((t = ctab) != NULL) 136166124Srafan for (cnt = 0; 137166124Srafan cnt < maxlen && (ch = *inp++) != '\n'; ++cnt) 13862449Speter *outp++ = t[ch]; 139166124Srafan else 140166124Srafan for (cnt = 0; 141166124Srafan cnt < maxlen && (ch = *inp++) != '\n'; ++cnt) 14250276Speter *outp++ = ch; 14362449Speter /* 144166124Srafan * Check for short record without a newline. Reassemble the 145166124Srafan * input block. 146166124Srafan */ 14762449Speter if (ch != '\n' && in.dbcnt < cbsz) { 148166124Srafan memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); 149166124Srafan break; 15062449Speter } 151166124Srafan 15250276Speter /* Adjust the input buffer numbers. */ 153166124Srafan in.dbcnt -= cnt; 154166124Srafan if (ch == '\n') 155166124Srafan --in.dbcnt; 156166124Srafan 157166124Srafan /* Pad short records with spaces. */ 158166124Srafan if (cnt < cbsz) 159166124Srafan (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt); 160166124Srafan else { 161166124Srafan /* 162166124Srafan * If the next character wouldn't have ended the 163166124Srafan * block, it's a truncation. 164166124Srafan */ 165166124Srafan if (!in.dbcnt || *inp != '\n') 16697049Speter ++st.trunc; 167166124Srafan 168166124Srafan /* Toss characters to a newline. */ 169166124Srafan for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt); 170166124Srafan if (!in.dbcnt) 17162449Speter intrunc = 1; 172166124Srafan else 173166124Srafan --in.dbcnt; 174166124Srafan } 17550276Speter 176166124Srafan /* Adjust output buffer numbers. */ 177166124Srafan out.dbp += cbsz; 178166124Srafan if ((out.dbcnt += cbsz) >= out.dbsz) 179166124Srafan dd_out(0); 180166124Srafan outp = out.dbp; 181166124Srafan } 18262449Speter in.dbp = in.db + in.dbcnt; 183166124Srafan} 184166124Srafan 18562449Spetervoid 186166124Srafanblock_close() 18762449Speter{ 188166124Srafan /* 18950276Speter * Copy any remaining data into the output buffer and pad to a record. 190166124Srafan * Don't worry about truncation or translation, the input buffer is 19162449Speter * always empty when truncating, and no characters have been added for 19250276Speter * translation. The bottom line is that anything left in the input 19362449Speter * buffer is a truncated record. Anything left in the output buffer 194166124Srafan * just wasn't big enough. 195166124Srafan */ 196166124Srafan if (in.dbcnt) { 197166124Srafan ++st.trunc; 198166124Srafan memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt); 199166124Srafan (void)memset(out.dbp + in.dbcnt, 200166124Srafan ctab ? ctab[' '] : ' ', cbsz - in.dbcnt); 201166124Srafan out.dbcnt += cbsz; 202166124Srafan } 203166124Srafan} 204166124Srafan 205166124Srafan/* 206166124Srafan * Convert fixed length (cbsz) records to variable length. Deletes any 207166124Srafan * trailing blanks and appends a newline. 208166124Srafan * 209166124Srafan * max in buffer: MAX(ibs, cbsz) + cbsz 210166124Srafan * max out buffer: obs + cbsz 211166124Srafan */ 21262449Spetervoid 21362449Speterunblock() 21462449Speter{ 21562449Speter int cnt; 21662449Speter u_char *inp, *t; 21750276Speter 21862449Speter /* Translation and case conversion. */ 21962449Speter if ((t = ctab) != NULL) 22062449Speter for (cnt = in.dbrcnt, inp = in.dbp; cnt--;) 22162449Speter *--inp = t[*inp]; 22262449Speter /* 22350276Speter * Copy records (max cbsz size chunks) into the output buffer. The 22462449Speter * translation has to already be done or we might not recognize the 22562449Speter * spaces. 22662449Speter */ 22762449Speter for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) { 22850276Speter for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t); 229166124Srafan if (t >= inp) { 230166124Srafan cnt = t - inp + 1; 231166124Srafan memmove(out.dbp, inp, cnt); 232166124Srafan out.dbp += cnt; 233166124Srafan out.dbcnt += cnt; 234166124Srafan } 23550276Speter ++out.dbcnt; 236166124Srafan *out.dbp++ = '\n'; 237166124Srafan if (out.dbcnt >= out.dbsz) 238166124Srafan dd_out(0); 239166124Srafan } 240174993Srafan if (in.dbcnt) 24162449Speter memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); 242174993Srafan in.dbp = in.db + in.dbcnt; 243174993Srafan} 24450276Speter 24562449Spetervoid 24650276Speterunblock_close() 247{ 248 int cnt; 249 u_char *t; 250 251 if (in.dbcnt) { 252 warnx("%s: short input record", in.name); 253 for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t); 254 if (t >= in.db) { 255 cnt = t - in.db + 1; 256 memmove(out.dbp, in.db, cnt); 257 out.dbp += cnt; 258 out.dbcnt += cnt; 259 } 260 ++out.dbcnt; 261 *out.dbp++ = '\n'; 262 } 263} 264