248 lines
4.5 KiB
C
Executable File
248 lines
4.5 KiB
C
Executable File
#ident "@(#)paste.c 1.14 94/11/17 SMI" /* SVr4.0 1.4 */
|
|
|
|
/*
|
|
* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
|
|
* All Rights Reserved
|
|
*
|
|
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
|
|
* The copyright notice above does not evidence any
|
|
* actual or intended publication of such source code.
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <locale.h>
|
|
#include <widec.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
|
|
|
|
#define MAXOPNF 12 /* maximal no. of open files (not with -s option) */
|
|
#define MAXOPNF_STR "12"
|
|
#define RUB '\177'
|
|
|
|
|
|
/*
|
|
* Function prototypes
|
|
*/
|
|
static void diag(char *, char *);
|
|
static int move(char *, wchar_t *);
|
|
static void usage();
|
|
|
|
|
|
main(int argc, char **argv)
|
|
{
|
|
int i, j, k, eofcount, nfiles, maxline, glue;
|
|
int delcount = 1;
|
|
int onefile = 0;
|
|
register int c;
|
|
wchar_t del[LINE_MAX];
|
|
wchar_t outbuf[LINE_MAX], l, t;
|
|
register wchar_t *p;
|
|
FILE *inptr[MAXOPNF];
|
|
int arg_ind;
|
|
int file_ind;
|
|
int error = 0;
|
|
|
|
|
|
/* Get locale variables from environment */
|
|
(void) setlocale(LC_ALL, "");
|
|
|
|
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
|
|
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
|
|
#endif
|
|
(void) textdomain(TEXT_DOMAIN);
|
|
|
|
del[0] = '\t';
|
|
maxline = LINE_MAX -2;
|
|
|
|
/* Get command arguments */
|
|
while ((c = getopt(argc, argv, "d:s")) != EOF) {
|
|
switch (c) {
|
|
case 'd' :
|
|
delcount = move(optarg, del);
|
|
if (delcount < 1)
|
|
diag("paste: no delimiters\n", NULL);
|
|
break;
|
|
|
|
case 's' :
|
|
onefile++;
|
|
break;
|
|
|
|
case '?':
|
|
usage();
|
|
|
|
/* NOTREACHED */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!onefile) { /* not -s option: parallel line merging */
|
|
|
|
/* Find explicit stdin and file names */
|
|
for (file_ind = 0, arg_ind = optind; arg_ind < argc &&
|
|
file_ind < MAXOPNF; arg_ind++) {
|
|
if (argv[arg_ind][0] == '-' &&
|
|
argv[arg_ind][1] == '\0') {
|
|
inptr[file_ind++] = stdin;
|
|
} else if (arg_ind >= optind) {
|
|
inptr[file_ind++] = fopen(argv[arg_ind], "r");
|
|
if (inptr[file_ind -1] == NULL) {
|
|
diag("paste: cannot open %s\n",
|
|
argv[arg_ind]);
|
|
}
|
|
}
|
|
}
|
|
if (arg_ind < argc) {
|
|
char maxopnf_buf[LINE_MAX];
|
|
(void) sprintf(maxopnf_buf, "%d", MAXOPNF);
|
|
diag("paste: too many files- limit %s\n", maxopnf_buf);
|
|
}
|
|
nfiles = file_ind;
|
|
|
|
do {
|
|
p = &outbuf[0];
|
|
eofcount = 0;
|
|
j = k = 0;
|
|
for (i = 0; i < nfiles; i++) {
|
|
while ((c = fgetwc(inptr[i])) != '\n' &&
|
|
c != EOF) {
|
|
if (++j <= maxline)
|
|
*p++ = c;
|
|
else {
|
|
diag(
|
|
"paste: line too long\n",
|
|
NULL);
|
|
}
|
|
}
|
|
if ((l = del[k]) != RUB)
|
|
*p++ = l;
|
|
|
|
k = (k + 1) % delcount;
|
|
|
|
if (c == EOF)
|
|
eofcount++;
|
|
}
|
|
if (l != RUB)
|
|
*--p = '\n';
|
|
else
|
|
*p = '\n';
|
|
*++p = 0;
|
|
if (eofcount < nfiles)
|
|
(void) printf("%ws", outbuf);
|
|
} while (eofcount < nfiles);
|
|
|
|
} else { /* -s option: serial file pasting (old 127 paste command) */
|
|
|
|
for (i = optind; i < argc; i++) {
|
|
p = &outbuf[0];
|
|
glue = 0;
|
|
j = 0;
|
|
k = 0;
|
|
t = 0;
|
|
if (argv[i][0] == '-' &&
|
|
argv[i][1] == '\0') {
|
|
inptr[0] = stdin;
|
|
} else if (i >= optind) {
|
|
inptr[0] = fopen(argv[i], "r");
|
|
if (inptr[0] == NULL) {
|
|
(void) fprintf(stderr, gettext(
|
|
"paste: cannot open %s\n"), argv[i]);
|
|
error = 1;
|
|
}
|
|
}
|
|
|
|
/* Argument not a file name */
|
|
if (inptr[0] == NULL) {
|
|
continue;
|
|
}
|
|
|
|
while ((c = fgetwc(inptr[0])) != EOF) {
|
|
if (j >= maxline) {
|
|
t = *--p;
|
|
*++p = 0;
|
|
(void) printf("%ws", outbuf);
|
|
p = &outbuf[0];
|
|
j = 0;
|
|
}
|
|
if (glue) {
|
|
glue = 0;
|
|
l = del[k];
|
|
if (l != RUB) {
|
|
*p++ = l;
|
|
t = l;
|
|
j++;
|
|
}
|
|
k = (k + 1) % delcount;
|
|
}
|
|
if (c != '\n') {
|
|
*p++ = c;
|
|
t = c;
|
|
j++;
|
|
} else glue++;
|
|
}
|
|
if (t != '\n') {
|
|
*p++ = '\n';
|
|
j++;
|
|
}
|
|
if (j > 0) {
|
|
*p = 0;
|
|
(void) printf("%ws", outbuf);
|
|
}
|
|
}
|
|
}
|
|
return (error);
|
|
}
|
|
|
|
|
|
static void
|
|
diag(char *s, char *arg)
|
|
{
|
|
(void) fprintf(stderr, gettext(s), arg);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
static int
|
|
move(char *from, wchar_t *to)
|
|
{
|
|
int i, n;
|
|
wchar_t wc;
|
|
|
|
i = 0;
|
|
while (*from) {
|
|
n = mbtowc(&wc, from, MB_CUR_MAX);
|
|
if (n <= 0)
|
|
return (0); /* invalid character as a delimiter */
|
|
from += n;
|
|
if (wc != L'\\') *to++ = wc;
|
|
else {
|
|
n = mbtowc(&wc, from, MB_CUR_MAX);
|
|
if (n <= 0)
|
|
return (0);
|
|
from += n;
|
|
switch (wc) {
|
|
case L'0' : *to++ = RUB;
|
|
break;
|
|
case L't' : *to++ = L'\t';
|
|
break;
|
|
case L'n' : *to++ = L'\n';
|
|
break;
|
|
default : *to++ = wc;
|
|
break;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
return (i);
|
|
}
|
|
|
|
|
|
static void
|
|
usage()
|
|
{
|
|
(void) fprintf(stderr, gettext(
|
|
"usage: paste [-s] [-d list] file \n\n"));
|
|
exit(1);
|
|
}
|