version 1.22, 2015/11/03 04:57:20 |
version 1.23, 2015/12/02 00:56:46 |
|
|
* SUCH DAMAGE. |
* SUCH DAMAGE. |
*/ |
*/ |
|
|
|
#include <assert.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <err.h> |
#include <err.h> |
#include <errno.h> |
#include <errno.h> |
|
|
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
|
|
|
char dchar[5]; |
|
int dlen; |
|
|
|
int bflag; |
int cflag; |
int cflag; |
char dchar; |
|
int dflag; |
int dflag; |
int fflag; |
int fflag; |
|
int nflag; |
int sflag; |
int sflag; |
|
|
|
void b_cut(FILE *, char *); |
void c_cut(FILE *, char *); |
void c_cut(FILE *, char *); |
void f_cut(FILE *, char *); |
void f_cut(FILE *, char *); |
void get_list(char *); |
void get_list(char *); |
|
|
void (*fcn)(FILE *, char *); |
void (*fcn)(FILE *, char *); |
int ch, rval; |
int ch, rval; |
|
|
setlocale (LC_ALL, ""); |
setlocale(LC_CTYPE, ""); |
|
|
if (pledge("stdio rpath", NULL) == -1) |
if (pledge("stdio rpath", NULL) == -1) |
err(1, "pledge"); |
err(1, "pledge"); |
|
|
dchar = '\t'; /* default delimiter is \t */ |
dchar[0] = '\t'; /* default delimiter */ |
|
dchar[1] = '\0'; |
|
dlen = 1; |
|
|
/* Since we don't support multi-byte characters, the -c and -b |
|
options are equivalent, and the -n option is meaningless. */ |
|
while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1) |
while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1) |
switch(ch) { |
switch(ch) { |
case 'b': |
case 'b': |
|
get_list(optarg); |
|
bflag = 1; |
|
break; |
case 'c': |
case 'c': |
fcn = c_cut; |
|
get_list(optarg); |
get_list(optarg); |
cflag = 1; |
cflag = 1; |
break; |
break; |
case 'd': |
case 'd': |
dchar = *optarg; |
if ((dlen = mblen(optarg, MB_CUR_MAX)) == -1) |
|
usage(); |
|
assert(dlen < sizeof(dchar)); |
|
(void)memcpy(dchar, optarg, dlen); |
|
dchar[dlen] = '\0'; |
dflag = 1; |
dflag = 1; |
break; |
break; |
case 'f': |
case 'f': |
get_list(optarg); |
get_list(optarg); |
fcn = f_cut; |
|
fflag = 1; |
fflag = 1; |
break; |
break; |
|
case 'n': |
|
nflag = 1; |
|
break; |
case 's': |
case 's': |
sflag = 1; |
sflag = 1; |
break; |
break; |
case 'n': |
|
break; |
|
case '?': |
case '?': |
default: |
default: |
usage(); |
usage(); |
|
|
argc -= optind; |
argc -= optind; |
argv += optind; |
argv += optind; |
|
|
if (fflag) { |
if (bflag + cflag + fflag != 1 || |
if (cflag) |
(nflag && !bflag) || |
usage(); |
((dflag || sflag) && !fflag)) |
} else if (!cflag || dflag || sflag) |
|
usage(); |
usage(); |
|
|
|
if (MB_CUR_MAX == 1) { |
|
nflag = 0; |
|
if (cflag) { |
|
bflag = 1; |
|
cflag = 0; |
|
} |
|
} |
|
|
|
fcn = fflag ? f_cut : (cflag || nflag) ? c_cut : b_cut; |
|
|
rval = 0; |
rval = 0; |
if (*argv) |
if (*argv) |
for (; *argv; ++argv) { |
for (; *argv; ++argv) { |
|
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
void |
void |
c_cut(FILE *fp, char *fname) |
b_cut(FILE *fp, char *fname) |
{ |
{ |
int ch, col; |
int ch, col; |
char *pos; |
char *pos; |
|
|
} |
} |
|
|
void |
void |
f_cut(FILE *fp, char *fname) |
c_cut(FILE *fp, char *fname) |
{ |
{ |
int ch, field, isdelim; |
static char *line = NULL; |
char *pos, *p, sep; |
static size_t linesz = 0; |
int output; |
ssize_t linelen; |
size_t len; |
char *cp, *pos, *maxpos; |
char *lbuf, *tbuf; |
int len; |
|
|
for (sep = dchar, tbuf = NULL; (lbuf = fgetln(fp, &len));) { |
while ((linelen = getline(&line, &linesz, fp)) != -1) { |
output = 0; |
if (line[linelen - 1] == '\n') |
if (lbuf[len - 1] != '\n') { |
line[linelen - 1] = '\0'; |
/* no newline at the end of the last line so add one */ |
|
if ((tbuf = malloc(len + 1)) == NULL) |
cp = line; |
err(1, NULL); |
pos = positions + 1; |
memcpy(tbuf, lbuf, len); |
maxpos = pos + maxval; |
tbuf[len] = '\n'; |
while(pos < maxpos && *cp != '\0') { |
lbuf = tbuf; |
len = mblen(cp, MB_CUR_MAX); |
|
if (len == -1) |
|
len = 1; |
|
pos += nflag ? len : 1; |
|
if (pos[-1] == '\0') |
|
cp += len; |
|
else |
|
while (len--) |
|
putchar(*cp++); |
} |
} |
for (isdelim = 0, p = lbuf;; ++p) { |
if (autostop) |
ch = *p; |
puts(cp); |
/* this should work if newline is delimiter */ |
else |
if (ch == sep) |
putchar('\n'); |
isdelim = 1; |
} |
if (ch == '\n') { |
} |
if (!isdelim && !sflag) |
|
(void)fwrite(lbuf, len, 1, stdout); |
void |
break; |
f_cut(FILE *fp, char *fname) |
} |
{ |
} |
static char *line = NULL; |
if (!isdelim) |
static size_t linesz = 0; |
|
ssize_t linelen; |
|
char *sp, *ep, *pos, *maxpos; |
|
int output; |
|
|
|
while ((linelen = getline(&line, &linesz, fp)) != -1) { |
|
if (line[linelen - 1] == '\n') |
|
line[linelen - 1] = '\0'; |
|
|
|
if ((ep = strstr(line, dchar)) == NULL) { |
|
if (!sflag) |
|
puts(line); |
continue; |
continue; |
|
} |
|
|
pos = positions + 1; |
pos = positions + 1; |
for (field = maxval, p = lbuf; field; --field, ++pos) { |
maxpos = pos + maxval; |
if (*pos) { |
output = 0; |
if (output++) |
sp = line; |
(void)putchar(sep); |
for (;;) { |
while ((ch = *p++) != '\n' && ch != sep) |
if (*pos++) { |
(void)putchar(ch); |
if (output) |
|
fputs(dchar, stdout); |
|
while (sp < ep) |
|
putchar(*sp++); |
|
output = 1; |
} else |
} else |
while ((ch = *p++) != '\n' && ch != sep) |
sp = ep; |
; |
if (*sp == '\0' || pos == maxpos) |
if (ch == '\n') |
|
break; |
break; |
|
sp += dlen; |
|
if ((ep = strstr(sp, dchar)) == NULL) |
|
ep = strchr(sp, '\0'); |
} |
} |
if (ch != '\n') { |
if (autostop) |
if (autostop) { |
puts(sp); |
if (output) |
else |
(void)putchar(sep); |
putchar('\n'); |
for (; (ch = *p) != '\n'; ++p) |
|
(void)putchar(ch); |
|
} else |
|
for (; (ch = *p) != '\n'; ++p) |
|
; |
|
} |
|
(void)putchar('\n'); |
|
} |
} |
if (tbuf) |
|
free(tbuf); |
|
} |
} |
|
|
void |
void |