V10/cmd/cut.c
static char sccsid[] = "@(#)cut.c 1.2";
#
/* cut : cut and paste columns of a table (projection of a relation) (GWRL) */
/* Release 1.5; handles single backspaces as produced by nroff */
# include <stdio.h> /* make: cc cut.c */
#include <errno.h>
# define NFIELDS 512 /* max no of fields or resulting line length */
# define BACKSPACE 8
main(argc, argv)
int argc;
char **argv;
{
int del = '\t';
int i, j, count, poscnt, r, s, t;
int endflag, supflag, cflag, fflag, backflag, filenr;
int sel[NFIELDS];
register int c;
register char *p1;
char *p2, outbuf[NFIELDS];
FILE *inptr;
endflag = supflag = cflag = fflag = 0;
for (i=0; i<NFIELDS; i++)
sel[i] = 0;
while (argc > 1 && argv[1][0] == '-'){
for (i = 1; (c = argv[1][i]) != '\0'; i++) {
switch(c) {
case 'd' :
del = argv[1][++i];
if (del == '\0') diag("no delimiter\n");
break;
case 's':
supflag++ ;
break;
case 'c':
cflag++ ;
break;
case 'f':
fflag++ ;
break;
default :
diag("Usage: cut [-s] [-d<char>] {-c<list> | -f<list>} file ...\n");
break;
}
if (!endflag && (cflag || fflag)) {
endflag = 1;
r = s = t = 0;
do {
c = argv[1][++i];
switch(c) {
case '-' :
if (r) diagl();
r = 1;
if (t == 0) s = 1;
else {
s = t;
t = 0;
}
continue;
case '\0' :
case ',' :
if (t >= NFIELDS) diagl();
if (r) {
if (t == 0) t = NFIELDS - 1;
if (t<s) diagl();
for(j = s; j <= t; j++) sel[j] = 1;
}
else sel[t] = (t > 0 ? 1 : 0);
r = s = t = 0;
if (c == '\0') {
i--;
break;
}
continue;
default :
if (c< '0' || c> '9') diagl();
t = 10*t + c - '0';
continue;
}
for (j = t = 0; j < NFIELDS; j++) t += sel[j];
if (t == 0) diag("no fields\n");
} while (c != '\0');
}
}
--argc;
++argv;
} /* end options */
if (!(cflag || fflag)) diagl();
--argc;
filenr = 1;
do { /* for all input files */
if (argc > 0) inptr = fopen(argv[filenr], "r");
else inptr = stdin;
if (inptr == NULL)
diag(argv[filenr]);
endflag = 0;
do { /* for all lines of a file */
count = poscnt = backflag = 0;
p1 = &outbuf[0] - 1 ;
p2 = p1;
do { /* for all char of the line */
c = fgetc(inptr);
if (c == EOF) {
endflag = 1;
break;
}
if (count == NFIELDS - 1) diag("line too long\n");
if (c != '\n') *++p1 = c;
if (cflag && (c == BACKSPACE)) backflag++ ;
else
{
if ( !backflag ) poscnt += 1 ;
else backflag-- ;
}
if ( backflag > 1 ) diag("cannot handle multiple adjacent backspaces\n");
if ( ((c == '\n') && count > 0) || c == del || cflag) {
count += 1;
if (fflag) poscnt = count ;
if (sel[poscnt]) p2 = p1;
else p1 = p2;
}
}while (c != '\n');
if ( !endflag && (count > 0 || !supflag)) {
if (*p1 == del) *p1 = '\0';
else *++p1 = '\0'; /*suppress trailing delimiter*/
puts(outbuf);
}
} while (!endflag) ;
fclose(inptr);
} while(++filenr <= argc);
}
diag(s)
char *s;
{
write(2, "cut: ", 5);
if(errno)
perror(s);
else
write(2,s,strlen(s));
exit(2);
}
diagl()
{
diag("bad list for c/f option\n");
}