conv.c revision 20420
119370Spst/*- 298948Sobrien * Copyright (c) 1991, 1993, 1994 398948Sobrien * The Regents of the University of California. All rights reserved. 4130809Smarcel * 519370Spst * This code is derived from software contributed to Berkeley by 619370Spst * Keith Muller of the University of California, San Diego and Lance 798948Sobrien * Visser of Convex Computer Corporation. 819370Spst * 998948Sobrien * Redistribution and use in source and binary forms, with or without 1098948Sobrien * modification, are permitted provided that the following conditions 1198948Sobrien * are met: 1298948Sobrien * 1. Redistributions of source code must retain the above copyright 1319370Spst * notice, this list of conditions and the following disclaimer. 1498948Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1598948Sobrien * notice, this list of conditions and the following disclaimer in the 1698948Sobrien * documentation and/or other materials provided with the distribution. 1798948Sobrien * 3. All advertising materials mentioning features or use of this software 1819370Spst * must display the following acknowledgement: 1998948Sobrien * This product includes software developed by the University of 2098948Sobrien * California, Berkeley and its contributors. 2198948Sobrien * 4. Neither the name of the University nor the names of its contributors 2298948Sobrien * may be used to endorse or promote products derived from this software 2319370Spst * without specific prior written permission. 2419370Spst * 2519370Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2619370Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2798948Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2898948Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2998948Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30130809Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3119370Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3219370Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3398948Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3419370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3519370Spst * SUCH DAMAGE. 3619370Spst * 3719370Spst * $Id: conv.c,v 1.5 1996/11/13 19:59:56 phk Exp $ 3819370Spst */ 3919370Spst 4098948Sobrien#ifndef lint 4119370Spststatic char const sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94"; 4298948Sobrien#endif /* not lint */ 4319370Spst 4498948Sobrien#include <sys/param.h> 4598948Sobrien 4698948Sobrien#include <err.h> 4798948Sobrien#include <string.h> 4819370Spst 4919370Spst#include "dd.h" 50130809Smarcel#include "extern.h" 51130809Smarcel 5219370Spst/* 5319370Spst * def -- 5419370Spst * Copy input to output. Input is buffered until reaches obs, and then 5519370Spst * output until less than obs remains. Only a single buffer is used. 5619370Spst * Worst case buffer calculation is (ibs + obs - 1). 5719370Spst */ 5898948Sobrienvoid 5998948Sobriendef() 6098948Sobrien{ 6119370Spst int cnt; 6219370Spst u_char *inp, *t; 6319370Spst 6498948Sobrien if ((t = ctab) != NULL) 6598948Sobrien for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp) 6619370Spst *inp = t[*inp]; 6798948Sobrien 6819370Spst /* Make the output buffer look right. */ 6998948Sobrien out.dbp = in.dbp; 7098948Sobrien out.dbcnt = in.dbcnt; 7146283Sdfr 7246283Sdfr if (in.dbcnt >= out.dbsz) { 7319370Spst /* If the output buffer is full, write it. */ 7419370Spst dd_out(0); 7519370Spst 7619370Spst /* 7719370Spst * Ddout copies the leftover output to the beginning of 7819370Spst * the buffer and resets the output buffer. Reset the 7919370Spst * input buffer to match it. 8019370Spst */ 8119370Spst in.dbp = out.dbp; 8219370Spst in.dbcnt = out.dbcnt; 8319370Spst } 8419370Spst} 85130809Smarcel 8619370Spstvoid 8719370Spstdef_close() 8819370Spst{ 8919370Spst /* Just update the count, everything is already in the buffer. */ 9019370Spst if (in.dbcnt) 9198948Sobrien out.dbcnt = in.dbcnt; 9219370Spst} 9319370Spst 9419370Spst/* 9546283Sdfr * Copy variable length newline terminated records with a max size cbsz 9619370Spst * bytes to output. Records less than cbs are padded with spaces. 9719370Spst * 9819370Spst * max in buffer: MAX(ibs, cbsz) 9919370Spst * max out buffer: obs + cbsz 10019370Spst */ 10119370Spstvoid 10219370Spstblock() 10319370Spst{ 10419370Spst static int intrunc; 10519370Spst int ch, cnt, maxlen; 10619370Spst u_char *inp, *outp, *t; 10719370Spst 10819370Spst /* 10919370Spst * Record truncation can cross block boundaries. If currently in a 11098948Sobrien * truncation state, keep tossing characters until reach a newline. 11119370Spst * Start at the beginning of the buffer, as the input buffer is always 11219370Spst * left empty. 11319370Spst */ 11419370Spst if (intrunc) { 11519370Spst for (inp = in.db, cnt = in.dbrcnt; 11698948Sobrien cnt && *inp++ != '\n'; --cnt); 11719370Spst if (!cnt) { 11819370Spst in.dbcnt = 0; 11919370Spst in.dbp = in.db; 12019370Spst return; 12119370Spst } 12219370Spst intrunc = 0; 12319370Spst /* Adjust the input buffer numbers. */ 12419370Spst in.dbcnt = cnt - 1; 12598948Sobrien in.dbp = inp + cnt - 1; 12619370Spst } 12719370Spst 12819370Spst /* 12919370Spst * Copy records (max cbsz size chunks) into the output buffer. The 13019370Spst * translation is done as we copy into the output buffer. 13119370Spst */ 13219370Spst ch = 0; 13319370Spst for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) { 13419370Spst maxlen = MIN(cbsz, in.dbcnt); 13519370Spst if ((t = ctab) != NULL) 13619370Spst for (cnt = 0; 13719370Spst cnt < maxlen && (ch = *inp++) != '\n'; ++cnt) 13819370Spst *outp++ = t[ch]; 13946283Sdfr else 14046283Sdfr for (cnt = 0; 14198948Sobrien cnt < maxlen && (ch = *inp++) != '\n'; ++cnt) 14298948Sobrien *outp++ = ch; 14398948Sobrien /* 14498948Sobrien * Check for short record without a newline. Reassemble the 14598948Sobrien * input block. 14646283Sdfr */ 14798948Sobrien if (ch != '\n' && in.dbcnt < cbsz) { 14898948Sobrien memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); 14998948Sobrien break; 150130809Smarcel } 15198948Sobrien 15298948Sobrien /* Adjust the input buffer numbers. */ 15398948Sobrien in.dbcnt -= cnt; 15498948Sobrien if (ch == '\n') 15598948Sobrien --in.dbcnt; 15698948Sobrien 15798948Sobrien /* Pad short records with spaces. */ 15898948Sobrien if (cnt < cbsz) 15998948Sobrien (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt); 16098948Sobrien else { 16119370Spst /* 16219370Spst * If the next character wouldn't have ended the 16319370Spst * block, it's a truncation. 16419370Spst */ 16598948Sobrien if (!in.dbcnt || *inp != '\n') 16698948Sobrien ++st.trunc; 16798948Sobrien 16898948Sobrien /* Toss characters to a newline. */ 16998948Sobrien for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt); 17098948Sobrien if (!in.dbcnt) 17119370Spst intrunc = 1; 17219370Spst else 17319370Spst --in.dbcnt; 174130809Smarcel } 175130809Smarcel 176130809Smarcel /* Adjust output buffer numbers. */ 177130809Smarcel out.dbp += cbsz; 178130809Smarcel if ((out.dbcnt += cbsz) >= out.dbsz) 17919370Spst dd_out(0); 18019370Spst outp = out.dbp; 18119370Spst } 18219370Spst in.dbp = in.db + in.dbcnt; 18319370Spst} 18498948Sobrien 18519370Spstvoid 18619370Spstblock_close() 18719370Spst{ 18819370Spst /* 18919370Spst * Copy any remaining data into the output buffer and pad to a record. 19019370Spst * Don't worry about truncation or translation, the input buffer is 19198948Sobrien * always empty when truncating, and no characters have been added for 19219370Spst * translation. The bottom line is that anything left in the input 19398948Sobrien * buffer is a truncated record. Anything left in the output buffer 19498948Sobrien * just wasn't big enough. 19519370Spst */ 19698948Sobrien if (in.dbcnt) { 19719370Spst ++st.trunc; 19898948Sobrien memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt); 19998948Sobrien (void)memset(out.dbp + in.dbcnt, 20098948Sobrien ctab ? ctab[' '] : ' ', cbsz - in.dbcnt); 20119370Spst out.dbcnt += cbsz; 20298948Sobrien } 20319370Spst} 20498948Sobrien 20598948Sobrien/* 20619370Spst * Convert fixed length (cbsz) records to variable length. Deletes any 20798948Sobrien * trailing blanks and appends a newline. 20819370Spst * 20919370Spst * max in buffer: MAX(ibs, cbsz) + cbsz 21019370Spst * max out buffer: obs + cbsz 21119370Spst */ 21298948Sobrienvoid 21398948Sobrienunblock() 21419370Spst{ 21519370Spst int cnt; 21698948Sobrien u_char *inp, *t; 21719370Spst 21846283Sdfr /* Translation and case conversion. */ 21946283Sdfr if ((t = ctab) != NULL) 22098948Sobrien for (cnt = in.dbrcnt, inp = in.dbp; cnt--;) 22146283Sdfr *--inp = t[*inp]; 22246283Sdfr /* 22346283Sdfr * Copy records (max cbsz size chunks) into the output buffer. The 22446283Sdfr * translation has to already be done or we might not recognize the 22546283Sdfr * spaces. 22646283Sdfr */ 22746283Sdfr for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) { 22846283Sdfr for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t); 22946283Sdfr if (t >= inp) { 23046283Sdfr cnt = t - inp + 1; 23146283Sdfr memmove(out.dbp, inp, cnt); 23246283Sdfr out.dbp += cnt; 23398948Sobrien out.dbcnt += cnt; 23498948Sobrien } 23598948Sobrien ++out.dbcnt; 23646283Sdfr *out.dbp++ = '\n'; 23719370Spst if (out.dbcnt >= out.dbsz) 23819370Spst dd_out(0); 23919370Spst } 24098948Sobrien if (in.dbcnt) 24198948Sobrien memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); 24298948Sobrien in.dbp = in.db + in.dbcnt; 24319370Spst} 24498948Sobrien 24598948Sobrienvoid 24698948Sobrienunblock_close() 24798948Sobrien{ 24898948Sobrien int cnt; 24998948Sobrien u_char *t; 25019370Spst 25119370Spst if (in.dbcnt) { 25219370Spst warnx("%s: short input record", in.name); 25398948Sobrien for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t); 25419370Spst if (t >= in.db) { 25519370Spst cnt = t - in.db + 1; 25619370Spst memmove(out.dbp, in.db, cnt); 25719370Spst out.dbp += cnt; 25898948Sobrien out.dbcnt += cnt; 25919370Spst } 26046283Sdfr ++out.dbcnt; 26146283Sdfr *out.dbp++ = '\n'; 26298948Sobrien } 26398948Sobrien} 26446283Sdfr