* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)conv.c 8.3 (Berkeley) %G%";
* Copy input to output. Input is buffered until reaches obs, and then
* output until less than obs remains. Only a single buffer is used.
* Worst case buffer calculation is (ibs + obs - 1).
for (inp
= in
.dbp
- (cnt
= in
.dbrcnt
); cnt
--; ++inp
)
/* Make the output buffer look right. */
if (in
.dbcnt
>= out
.dbsz
) {
/* If the output buffer is full, write it. */
* Ddout copies the leftover output to the beginning of
* the buffer and resets the output buffer. Reset the
* input buffer to match it.
/* Just update the count, everything is already in the buffer. */
* Copy variable length newline terminated records with a max size cbsz
* bytes to output. Records less than cbs are padded with spaces.
* max in buffer: MAX(ibs, cbsz)
* max out buffer: obs + cbsz
* Record truncation can cross block boundaries. If currently in a
* truncation state, keep tossing characters until reach a newline.
* Start at the beginning of the buffer, as the input buffer is always
for (inp
= in
.db
, cnt
= in
.dbrcnt
;
cnt
&& *inp
++ != '\n'; --cnt
);
/* Adjust the input buffer numbers. */
* Copy records (max cbsz size chunks) into the output buffer. The
* translation is done as we copy into the output buffer.
for (inp
= in
.dbp
- in
.dbcnt
, outp
= out
.dbp
; in
.dbcnt
;) {
maxlen
= MIN(cbsz
, in
.dbcnt
);
cnt
< maxlen
&& (ch
= *inp
++) != '\n'; ++cnt
)
cnt
< maxlen
&& (ch
= *inp
++) != '\n'; ++cnt
)
* Check for short record without a newline. Reassemble the
if (ch
!= '\n' && in
.dbcnt
< cbsz
) {
memmove(in
.db
, in
.dbp
- in
.dbcnt
, in
.dbcnt
);
/* Adjust the input buffer numbers. */
/* Pad short records with spaces. */
(void)memset(outp
, ctab
? ctab
[' '] : ' ', cbsz
- cnt
);
* If the next character wouldn't have ended the
* block, it's a truncation.
if (!in
.dbcnt
|| *inp
!= '\n')
/* Toss characters to a newline. */
for (; in
.dbcnt
&& *inp
++ != '\n'; --in
.dbcnt
);
/* Adjust output buffer numbers. */
if ((out
.dbcnt
+= cbsz
) >= out
.dbsz
)
in
.dbp
= in
.db
+ in
.dbcnt
;
* Copy any remaining data into the output buffer and pad to a record.
* Don't worry about truncation or translation, the input buffer is
* always empty when truncating, and no characters have been added for
* translation. The bottom line is that anything left in the input
* buffer is a truncated record. Anything left in the output buffer
* just wasn't big enough.
memmove(out
.dbp
, in
.dbp
- in
.dbcnt
, in
.dbcnt
);
(void)memset(out
.dbp
+ in
.dbcnt
,
ctab
? ctab
[' '] : ' ', cbsz
- in
.dbcnt
);
* Convert fixed length (cbsz) records to variable length. Deletes any
* trailing blanks and appends a newline.
* max in buffer: MAX(ibs, cbsz) + cbsz
* max out buffer: obs + cbsz
/* Translation and case conversion. */
for (cnt
= in
.dbrcnt
, inp
= in
.dbp
; cnt
--;)
* Copy records (max cbsz size chunks) into the output buffer. The
* translation has to already be done or we might not recognize the
for (inp
= in
.db
; in
.dbcnt
>= cbsz
; inp
+= cbsz
, in
.dbcnt
-= cbsz
) {
for (t
= inp
+ cbsz
- 1; t
>= inp
&& *t
== ' '; --t
);
memmove(out
.dbp
, inp
, cnt
);
if (out
.dbcnt
>= out
.dbsz
)
memmove(in
.db
, in
.dbp
- in
.dbcnt
, in
.dbcnt
);
in
.dbp
= in
.db
+ in
.dbcnt
;
warnx("%s: short input record", in
.name
);
for (t
= in
.db
+ in
.dbcnt
- 1; t
>= in
.db
&& *t
== ' '; --t
);
memmove(out
.dbp
, in
.db
, cnt
);