Importing usr.bin/paste

Replaces commands/paste. No Minix-specific changes needed.

Change-Id: I92a6813502d552ad005ba6e856ce573508fc9f24
This commit is contained in:
Thomas Cort 2013-10-27 19:43:02 -04:00
parent f3c74513eb
commit f1f496697e
10 changed files with 361 additions and 513 deletions

View file

@ -17,7 +17,7 @@ SUBDIR= add_route arp ash at backup btrace \
lpd lspci mail MAKEDEV \
mined mkfifo \
mount mt netconf \
nonamed od paste patch \
nonamed od patch \
ping postinstall poweroff prep printroot \
profile progressbar pr_routes ps pwdauth \
ramdisk rarpd rawspeed rcp readclock \

View file

@ -1,4 +0,0 @@
PROG= paste
MAN=
.include <bsd.prog.mk>

View file

@ -1,456 +0,0 @@
/* paste - laminate files Author: David Ihnat */
/* Paste - a recreation of the Unix(Tm) paste(1) command.
*
* syntax: paste file1 file2 ... paste -dLIST file1 file2 ... paste -s [-dLIST]
* file1 file2 ...
*
* Copyright (C) 1984 by David M. Ihnat
*
* This program is a total rewrite of the Bell Laboratories Unix(Tm) command of
* the same name, as of System V. It contains no proprietary code, and
* therefore may be used without violation of any proprietary agreements
* whatsoever. However, you will notice that the program is copyrighted by
* me. This is to assure the program does *not* fall into the public domain.
* Thus, I may specify just what I am now: This program may be freely copied
* and distributed, provided this notice remains; it may not be sold for
* profit without express written consent of the author. Please note that I
* recreated the behavior of the Unix(Tm) 'paste' command as faithfully as
* possible, with minor exceptions (noted below); however, I haven't run a
* full set of regression * tests. Thus, the user of this program accepts
* full responsibility for any effects or loss; in particular, the author is
* not responsible for any losses, explicit or incidental, that may be
* incurred through use of this program.
*
* The changes to the program, with one exception, are transparent to a user
* familiar with the Unix command of the same name. These changes are:
*
* 1) The '-s' option had a bug in the Unix version when used with multiple
* files. (It would repeat each file in a list, i.e., for
*
* paste -s file1 file2 file3
*
* it would list
*
* <file1\n><file1\n><file2\n><file1\n><file2\n><file3\n>
*
* I fixed this, and reported the bug to the providers of the command in Unix.
*
* 2) The list of valid escape sequences has been expanded to include \b,\f,
* and \r. (Just because *I* can't imagine why you'd want to use them
* doesn't mean I should keep them from you.)
*
* 3) There is no longer any restriction on line length.
*
* I ask that any bugs (and, if possible, fixes) be reported to me when
* possible. -David Ihnat (312) 784-4544 ihuxx!ignatz
*/
/* Modified to run under MINIX 1.1 by David O. Tinker (416) 978-3636
* (utgpu!dtinker) Sept. 19, 1987
*/
/* Modified to conform to POSIX 1003.2/Draft10 standard 23rd Sept. 1990
* Changes:
* - the arguments can be in any order
* - removed the ToUpper function
* by Thomas Brupbacher (tobr@mw.lpc.ethz.ch)
*/
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* I'd love to use enums, but not everyone has them. Portability, y'know. */
#define NODELIM 1
#define USAGE 2
#define BADFILE 3
#define TOOMANY 4
#define TAB '\t'
#define NL '\n'
#define BS '\b'
#define FF '\f'
#define CR '\r'
#define DEL '\177'
#define SPACE ' '
#define BACKSLASH '\\'
#define _MAXSZ 512
#define _MAXFILES 12
#define CLOSED ((FILE *)-1)
#define ENDLIST ((FILE *)-2)
char *cmdnam;
short int sflag;
static char default_delims[] = {TAB}; /* default delimiter string */
char *delims; /* the pointer to the delimiters */
int number_of_delims = 1; /* number of delimiters to use */
int main(int argc, char **argv);
void docol(int nfiles, char **fnamptr);
void doserial(int nfiles, char **fnamptr);
void delimbuild(char *strptr);
void prerr(int etype, char *estring);
int main(argc, argv)
int argc;
char **argv;
{
char **arg_ptr; /* used to save argv, needed for docol() etc */
int num_files = 0; /* Number of filenames specified on cmd line */
sflag = 0;
delims = default_delims; /* use default delimiters */
cmdnam = *argv;
if (argc >= 2) {
/* Skip invocation name */
argv++;
argc--;
/* Save argv */
arg_ptr = argv;
/* First, parse input options */
while (argc-- > 0) {
if (argv[0][0] == '-' && argv[0][1] != '\0') {
switch (argv[0][1]) {
case 'd':
/* Delimiter character(s) */
if (*(++argv) == '\0')
prerr(NODELIM, "");
else
delimbuild(*(argv));
argc--;
break;
case 's': sflag++; break;
default: prerr(USAGE, "");
}
argv++;
} else {
num_files++;
argv++;
}
}
/* If there are more than MAX_FILES files on the command
* line, exit with error message. */
if (num_files > _MAXFILES) prerr(TOOMANY, "");
/* If no files specified, simply exit. Otherwise, if not the
* old '-s' option, process all files. If '-s', then process
* files one-at-a-time. */
if (!sflag)
docol(num_files, arg_ptr); /* Column paste */
else
doserial(num_files, arg_ptr); /* Serial paste */
exit(0);
} else
prerr(USAGE, "");
return(0);
}
void docol(nfiles, fnamptr)
int nfiles;
char **fnamptr;
{
char iobuff[_MAXSZ]; /* i/o buffer for the fgets */
short int somedone; /* flag for blank field handling */
/* There is a strange case where all files are just ready to be
* closed, or will on this round. In that case, the string of
* delimiters must be preserved. delbuf[1] ->delbuf[MAXFILES+1]
* provides intermediate storage for closed files, if needed;
* delbuf[0] is the current index.
*/
char delbuf[_MAXFILES + 2];
FILE *fileptr[_MAXFILES + 1];
int filecnt; /* Set to number of files to process */
register char *delimptr; /* Cycling delimiter pointer */
int index; /* Working variable */
int strend; /* End of string in buffer */
/* Perform column paste. First, attempt to open all files. (This
* could be expanded to an infinite number of files, but at the
* (considerable) expense of remembering the file and its current
* offset, then opening/reading/closing. The commands' utility
* doesn't warrant the effort; at least, to me...)
*/
for (filecnt = 0; (nfiles > 0); fnamptr++) {
if ((fnamptr[0][0] == '-') && (fnamptr[0][1] != '\0')) {
if (fnamptr[0][1] == 'd') fnamptr++;
} else {
nfiles--;
if (fnamptr[0][0] == '-') {
fileptr[filecnt++] = stdin;
} else {
fileptr[filecnt] = fopen(fnamptr[0], "r");
if (fileptr[filecnt++] == NULL)
prerr(BADFILE, *fnamptr);
}
}
}
fileptr[filecnt] = ENDLIST; /* End of list. */
/* Have all files. Now, read a line from each file, and output to
* stdout. Notice that the old 511 character limitation on the line
* length no longer applies, since this program doesn't do the
* buffering. Do this until you go through the loop and don't
* successfully read from any of the files.
*/
for (; filecnt;) {
somedone = 0; /* Blank field handling flag */
delimptr = delims; /* Start at beginning of delim list */
delbuf[0] = 0; /* No squirreled delims */
for (index = 0; (fileptr[index] != ENDLIST) && filecnt; index++) {
/* Read a line and immediately output. If it's too
* big for the buffer, then dump what was read and go
* back for more.
*
* Otherwise, if it is from the last file, then leave
* the carriage return in place; if not, replace with
* a delimiter (if any)
*/
strend = 0; /* Set so can easily detect EOF */
if (fileptr[index] != CLOSED)
while (fgets(iobuff, (_MAXSZ - 1),
fileptr[index]) != NULL) {
strend = strlen(iobuff);/* Did the buf fill? */
if (strend == (_MAXSZ - 1)) {
/* Gosh, what a long line. */
fputs(iobuff, stdout);
strend = 0;
continue;
}
/* Ok got whole line in buffer. */
break; /* Out of loop for this file */
}
/* Ended either on an EOF (well, actually NULL
* return-- it *could* be some sort of file error,
* but but if the file was opened successfully, this
* is unlikely. Besides, error checking on streams
* doesn't allow us to decide exactly what went
* wrong, so I'm going to be very Unix-like and
* ignore it!), or a closed file, or a received line.
* If an EOF, close the file and mark it in the list.
* In any case, output the delimiter of choice.
*/
if (!strend) {
if (fileptr[index] != CLOSED) {
fclose(fileptr[index]);
fileptr[index] = CLOSED;
filecnt--;
}
/* Is this the end of the whole thing? */
if ((fileptr[index + 1] == ENDLIST) && !somedone)
continue; /* EXITS */
/* Ok, some files not closed this line. Last file? */
if (fileptr[index + 1] == ENDLIST) {
if (delbuf[0]) {
fputs(&delbuf[1], stdout);
delbuf[0] = 0;
}
putc((int) NL, stdout);
continue; /* Next read of files */
} else {
/* Closed file; setup delim */
if (*delimptr != DEL) {
delbuf[0]++;
delbuf[delbuf[0]] = *delimptr++;
delbuf[delbuf[0] + 1] = '\0';
} else
delimptr++;
}
/* Reset end of delimiter string if necessary */
if (*delimptr == '\0') delimptr = delims;
} else {
/* Some data read. */
somedone++;
/* Any saved delims? */
if (delbuf[0]) {
fputs(&delbuf[1], stdout);
delbuf[0] = 0;
}
/* If last file, last char will be NL. */
if (fileptr[index + 1] != ENDLIST) {
if (*delimptr == DEL) {
delimptr++;
iobuff[strend - 1] = '\0';/* No delim*/
} else
iobuff[strend - 1] = *delimptr++;
}
if (*delimptr == '\0') delimptr = delims;
/* Now dump the buffer */
fputs(iobuff, stdout);
fflush(stdout);
}
}
}
}
void doserial(nfiles, fnamptr)
int nfiles;
char **fnamptr;
{
/* Do serial paste. Simply scarf characters, performing
* one-character buffering to facilitate delim processing.
*/
register int charnew, charold;
register char *delimptr;
register FILE *fileptr;
for (; nfiles != 0; fnamptr++) {
if ((fnamptr[0][0] == '-') && (fnamptr[0][1] != '\0')) {
if (fnamptr[0][1] == 'd') fnamptr++;
} else {
if (fnamptr[0][0] == '-') {
fileptr = stdin;
} else {
fileptr = fopen(*fnamptr, "r");
if (fileptr == NULL) prerr(BADFILE, *fnamptr);
}
/* The file is open; just keep taking characters,
* stashing them in charnew; output charold,
* converting to the appropriate delimiter character
* if needful. After the EOF, simply output
* 'charold' if it's a newline; otherwise, output it
* and then a newline.
*/
delimptr = delims; /* Set up for delimiter string */
if ((charold = getc(fileptr)) == EOF) {
/* Empty file! */
putc(NL, stdout);
fflush(stdout);
continue; /* Go on to the next file */
}
/* Ok, 'charold' is set up. Hit it! */
while ((charnew = getc(fileptr)) != EOF) {
/* Ok, process the old character */
if (charold == NL) {
if (*delimptr != DEL)
putc((int) *delimptr++, stdout);
/* Reset pointer at end of delimiter string */
if (*delimptr == '\0') delimptr = delims;
} else
putc(charold, stdout);
charold = charnew;
}
/* Ok, hit EOF. Process that last character */
putc(charold, stdout);
if ((char) charold != NL) putc(NL, stdout);
fflush(stdout);
nfiles--;
}
}
}
void delimbuild(strptr)
char *strptr;
{
/* Process the delimiter string into something that can be used by
* the routines. This involves, primarily, collapsing the backslash
* representations of special characters into their actual values,
* and terminating the string in a manner that the routines can
* recognize. The set of possible backslash characters has been
* expanded beyond that recognized by the vanilla Unix(Tm) version.
*/
register char *strout;
delims = strptr; /* delims now points to argv[...] */
strout = strptr; /* Start at the same place, anyway */
while (*strptr) {
if (*strptr != '\\') /* Is it an escape character? */
*strout++ = *strptr++; /* No, just transfer it */
else {
strptr++; /* Get past escape character */
switch (*strptr) {
case '0': *strout++ = DEL; break;
case 't': *strout++ = TAB; break;
case 'n': *strout++ = NL; break;
case 'b': *strout++ = BS; break;
case 'f': *strout++ = FF; break;
case 'r': *strout++ = CR; break;
case '\\':
*strout++ = BACKSLASH;
break;
default: *strout++ = *strptr;
}
strptr++;
}
}
*strout = '\0'; /* Heaven forfend that we forget this! */
}
void prerr(etype, estring)
int etype;
char *estring;
{
switch (etype) {
case USAGE:
fprintf(stderr, "%s : Usage: %s [-s] [-d <delimiters>] file1 file2 ...\n", cmdnam, cmdnam);
break;
case NODELIM:
fprintf(stderr, "%s : no delimiters\n", cmdnam);
break;
case BADFILE:
fprintf(stderr, "%s : %s : cannot open\n", cmdnam, estring);
break;
case TOOMANY:
fprintf(stderr, "%s : too many files\n", cmdnam);
break;
}
exit(1);
}

View file

@ -12,7 +12,7 @@ MAN= ash.1 at.1 \
look.1 lp.1 lspci.1 mail.1 \
mixer.1 \
mkproto.1 mount.1 mt.1 od.1 \
paste.1 ping.1 playwave.1 prep.1 \
ping.1 playwave.1 prep.1 \
profile.1 ps.1 rcp.1 recwave.1 \
remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \
shar.1 sleep.1 spell.1 \

View file

@ -1,50 +0,0 @@
.TH PASTE 1
.SH NAME
paste \- paste multiple files together
.SH SYNOPSIS
\fBpaste\fR [\fB\-s\fR]\fR [\fB\-d\fI list\fR] \fIfile...\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH OPTIONS
.TP 5
.B \-d
# Set delimiter used to separate columns to \fIlist\fR.
.TP 5
.B \-s
# Print files sequentially, file \fIk\fR on line \fIk\fR.
.SH EXAMPLES
.TP 20
.B paste file1 file2
# Print \fIfile1\fR in col 1, \fIfile2\fR in col 2
.TP 20
.B paste \-s f1 f2
# Print \fIf1\fR on line 1 and \fIf2\fR on line 2
.TP 20
.B paste -d : file1 file2
# Print the lines separated by a colon
.SH DESCRIPTION
.PP
\fIPaste\fR concatenates corresponding lines of the given input files
and writes them to standard output. The lines of the different files
are separated by the delimiters given with the option \-s\fR. If
no list is given, a tab is substituted for every linefeed, except the last one.
If end-of-file is hit on an input file, subsequent lines are empty.
Suppose a set of \fIk\fR files each has one word per line.
Then the \fIpaste\fR output will have \fIk\fR columns,
with the contents of file \fIj\fR in column \fIj\fR.
If the \fB\-s\fR flag is given, then the first
file is on line 1, the second file on line 2, etc.
In effect, \fB\-s\fR turns the output sideways.
.PP
If a list of delimiters is given, they are used in turn. The C escape
sequences \\n, \\t, \\\\, and \\0 are used for linefeed, tab, backslash, and
the null string, respectively.

View file

@ -195,6 +195,7 @@
2012/10/17 12:00:00,usr.bin/nvi
2010/05/14 17:28:23,usr.bin/newgrp
2012/10/17 12:00:00,usr.bin/passwd
2012/10/17 12:00:00,usr.bin/paste
2013/10/24 12:00:00,usr.bin/pr
2013/10/17 12:00:00,usr.bin/printenv
2012/10/17 12:00:00,usr.bin/printf

View file

@ -19,7 +19,7 @@ SUBDIR= asa \
mkdep mktemp \
\
nbperf newgrp nice nl nohup nvi \
passwd pr \
passwd paste pr \
printenv printf pwhash \
renice rev \
\

6
usr.bin/paste/Makefile Normal file
View file

@ -0,0 +1,6 @@
# $NetBSD: Makefile,v 1.5 2009/04/14 22:15:24 lukem Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= paste
.include <bsd.prog.mk>

118
usr.bin/paste/paste.1 Normal file
View file

@ -0,0 +1,118 @@
.\" $NetBSD: paste.1,v 1.7 2003/08/07 11:15:28 agc Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Adam S. Moskowitz and the Institute of Electrical and Electronics
.\" Engineers, Inc.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)paste.1 8.1 (Berkeley) 6/6/93
.\" $NetBSD: paste.1,v 1.7 2003/08/07 11:15:28 agc Exp $
.\"
.Dd June 6, 1993
.Dt PASTE 1
.Os
.Sh NAME
.Nm paste
.Nd merge corresponding or subsequent lines of files
.Sh SYNOPSIS
.Nm
.Op Fl s
.Op Fl d Ar list
.Ar file ...
.Sh DESCRIPTION
The
.Nm
utility concatenates the corresponding lines of the given input files,
replacing all but the last file's newline characters with a single tab
character, and writes the resulting lines to standard output.
If end-of-file is reached on an input file while other input files
still contain data, the file is treated as if it were an endless source
of empty lines.
.Pp
The options are as follows:
.Bl -tag -width Fl
.It Fl d Ar list
Use one or more of the provided characters to replace the newline
characters instead of the default tab.
The characters in
.Ar list
are used circularly, i.e., when
.Ar list
is exhausted the first character from
.Ar list
is reused.
This continues until a line from the last input file (in default operation)
or the last line in each file (using the -s option) is displayed, at which
time
.Nm
begins selecting characters from the beginning of
.Ar list
again.
.Pp
The following special characters can also be used in list:
.Pp
.Bl -tag -width flag -compact
.It Li \en
newline character
.It Li \et
tab character
.It Li \e\e
backslash character
.It Li \e0
Empty string (not a null character).
.El
.Pp
Any other character preceded by a backslash is equivalent to the
character itself.
.It Fl s
Concatenate all of the lines of each separate input file in command line
order.
The newline character of every line except the last line in each input
file is replaced with the tab character, unless otherwise specified by
the -d option.
.El
.Pp
If
.Ql Fl
is specified for one or more of the input files, the standard
input is used; standard input is read one line at a time, circularly,
for each instance of
.Ql Fl .
.Pp
The
.Nm
utility exits 0 on success, and \*[Gt]0 if an error occurs.
.Sh SEE ALSO
.Xr cut 1
.Sh STANDARDS
The
.Nm
utility is expected to be
.St -p1003.2
compatible.

233
usr.bin/paste/paste.c Normal file
View file

@ -0,0 +1,233 @@
/* $NetBSD: paste.c,v 1.16 2011/09/06 18:24:43 joerg Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam S. Moskowitz of Menlo Consulting.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)paste.c 8.1 (Berkeley) 6/6/93";*/
__RCSID("$NetBSD: paste.c,v 1.16 2011/09/06 18:24:43 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void parallel(int, char **);
static void sequential(char **);
static int tr(char *);
__dead static void usage(void);
static char dflt_delim[] = "\t";
static char *delim = dflt_delim;
static int delimcnt = 1;
int
main(int argc, char **argv)
{
int ch, seq;
seq = 0;
while ((ch = getopt(argc, argv, "d:s")) != -1) {
switch (ch) {
case 'd':
delim = strdup(optarg);
delimcnt = tr(delim);
break;
case 's':
seq = 1;
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (seq)
sequential(argv);
else
parallel(argc, argv);
exit(0);
}
static void
parallel(int argc, char **argv)
{
char ch, *dp, *line;
FILE **fpp, *fp;
size_t line_len;
int cnt, output;
fpp = calloc(argc, sizeof *fpp);
if (fpp == NULL)
err(1, "calloc");
for (cnt = 0; cnt < argc; cnt++) {
if (strcmp(argv[cnt], "-") == 0)
fpp[cnt] = stdin;
else if (!(fpp[cnt] = fopen(argv[cnt], "r")))
err(1, "%s", argv[cnt]);
}
for (;;) {
/* Start with the NUL at the end of 'delim' ... */
dp = delim + delimcnt;
output = 0;
for (cnt = 0; cnt < argc; cnt++) {
fp = fpp[cnt];
if (fp == NULL)
continue;
line = fgetln(fp, &line_len);
if (line == NULL) {
/* Assume EOF */
if (fp != stdin)
fclose(fp);
fpp[cnt] = NULL;
continue;
}
/* Output enough separators to catch up */
do {
ch = *dp++;
if (ch)
putchar(ch);
if (dp >= delim + delimcnt)
dp = delim;
} while (++output <= cnt);
/* Remove any trailing newline - check for last line */
if (line[line_len - 1] == '\n')
line_len--;
printf("%.*s", (int)line_len, line);
}
if (!output)
break;
/* Add separators to end of line */
while (++output <= cnt) {
ch = *dp++;
if (ch)
putchar(ch);
if (dp >= delim + delimcnt)
dp = delim;
}
putchar('\n');
}
free(fpp);
}
static void
sequential(char **argv)
{
FILE *fp;
int cnt;
char ch, *p, *dp;
char buf[_POSIX2_LINE_MAX + 1];
for (; (p = *argv) != NULL; ++argv) {
if (p[0] == '-' && !p[1])
fp = stdin;
else if (!(fp = fopen(p, "r"))) {
warn("%s", p);
continue;
}
if (fgets(buf, sizeof(buf), fp)) {
for (cnt = 0, dp = delim;;) {
if (!(p = strchr(buf, '\n')))
err(1, "%s: input line too long.",
*argv);
*p = '\0';
(void)printf("%s", buf);
if (!fgets(buf, sizeof(buf), fp))
break;
if ((ch = *dp++) != 0)
putchar(ch);
if (++cnt == delimcnt) {
dp = delim;
cnt = 0;
}
}
putchar('\n');
}
if (fp != stdin)
(void)fclose(fp);
}
}
static int
tr(char *arg)
{
int cnt;
char ch, *p;
for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
if (ch == '\\')
switch(ch = *p++) {
case 'n':
*arg = '\n';
break;
case 't':
*arg = '\t';
break;
case '0':
*arg = '\0';
break;
default:
*arg = ch;
break;
} else
*arg = ch;
if (!cnt)
errx(1, "no delimiters specified.");
*arg = '\0';
return(cnt);
}
static void
usage(void)
{
(void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
exit(1);
}