version 1.21, 2018/07/11 11:42:17 |
version 1.22, 2018/07/29 11:27:14 |
|
|
|
|
#include <ctype.h> |
#include <ctype.h> |
#include <err.h> |
#include <err.h> |
|
#include <locale.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
|
|
struct openfile { /* open file structure */ |
struct openfile { /* open file structure */ |
FILE *fp; /* file pointer */ |
FILE *fp; /* file pointer */ |
|
int minwidth; /* pad this column to this width */ |
|
int maxwidth; /* truncate this column */ |
short eof; /* eof flag */ |
short eof; /* eof flag */ |
short pad; /* pad flag for missing columns */ |
short pad; /* pad flag for missing columns */ |
char eol; /* end of line character */ |
char eol; /* end of line character */ |
|
char align; /* '0' for zero fill, '-' for left align */ |
char *sepstring; /* string to print before each line */ |
char *sepstring; /* string to print before each line */ |
char *format; /* printf(3) style string spec. */ |
|
} input[NOFILE_MAX + 1]; /* last one is for the last -s arg. */ |
} input[NOFILE_MAX + 1]; /* last one is for the last -s arg. */ |
#define INPUTSIZE sizeof(input) / sizeof(*input) |
#define INPUTSIZE sizeof(input) / sizeof(*input) |
|
|
|
|
char line[BIGBUFSIZ]; |
char line[BIGBUFSIZ]; |
char *linep; |
char *linep; |
|
|
|
int mbswidth_truncate(char *, int); /* utf8.c */ |
|
|
void usage(void); |
void usage(void); |
char *gatherline(struct openfile *); |
char *gatherline(struct openfile *); |
void getargs(int, char *[]); |
void getargs(int, char *[]); |
|
|
{ |
{ |
int i; |
int i; |
|
|
|
setlocale(LC_CTYPE, ""); |
|
|
if (pledge("stdio rpath", NULL) == -1) |
if (pledge("stdio rpath", NULL) == -1) |
err(1, "pledge"); |
err(1, "pledge"); |
|
|
|
|
getargs(int argc, char *argv[]) |
getargs(int argc, char *argv[]) |
{ |
{ |
struct openfile *ip = input; |
struct openfile *ip = input; |
char *p; |
const char *errstr; |
|
char *p, *q; |
int ch, P, S, F, T; |
int ch, P, S, F, T; |
size_t siz; |
|
|
|
P = S = F = T = 0; /* capitalized options */ |
P = S = F = T = 0; /* capitalized options */ |
while (optind < argc) { |
while (optind < argc) { |
|
|
case 'F': case 'f': |
case 'F': case 'f': |
F = (ch == 'F'); |
F = (ch == 'F'); |
/* Validate format string argument. */ |
/* Validate format string argument. */ |
for (p = optarg; *p != '\0'; p++) |
p = optarg; |
if (!isdigit((unsigned char)*p) && |
if (*p == '0' || *p == '-') |
*p != '.' && *p != '-') |
ip->align = *p++; |
errx(1, "%s: invalid width specified", |
else |
optarg); |
ip->align = ' '; |
/* '%' + width + 's' + '\0' */ |
if ((q = strchr(p, '.')) != NULL) |
siz = p - optarg + 3; |
*q++ = '\0'; |
if ((p = realloc(ip->format, siz)) == NULL) |
if (*p != '\0') { |
err(1, NULL); |
ip->minwidth = strtonum(p, 1, INT_MAX, |
snprintf(p, siz, "%%%ss", optarg); |
&errstr); |
ip->format = p; |
if (errstr != NULL) |
|
errx(1, "minimum width is %s: %s", |
|
errstr, p); |
|
} |
|
if (q != NULL) { |
|
ip->maxwidth = strtonum(q, 1, INT_MAX, |
|
&errstr); |
|
if (errstr != NULL) |
|
errx(1, "maximum width is %s: %s", |
|
errstr, q); |
|
} else |
|
ip->maxwidth = INT_MAX; |
break; |
break; |
case 'S': case 's': |
case 'S': case 's': |
S = (ch == 'S'); |
S = (ch == 'S'); |
|
|
ip->pad = P; |
ip->pad = P; |
if (ip->sepstring == NULL) |
if (ip->sepstring == NULL) |
ip->sepstring = S ? (ip-1)->sepstring : ""; |
ip->sepstring = S ? (ip-1)->sepstring : ""; |
if (ip->format == NULL) |
|
ip->format = (P || F) ? (ip-1)->format : "%s"; |
|
if (ip->eol == '\0') |
if (ip->eol == '\0') |
ip->eol = T ? (ip-1)->eol : '\n'; |
ip->eol = T ? (ip-1)->eol : '\n'; |
|
if (ip->align == '\0') { |
|
if (F || P) { |
|
ip->align = (ip-1)->align; |
|
ip->minwidth = (ip-1)->minwidth; |
|
ip->maxwidth = (ip-1)->maxwidth; |
|
} else |
|
ip->maxwidth = INT_MAX; |
|
} |
ip++; |
ip++; |
optind++; |
optind++; |
break; |
break; |
|
|
{ |
{ |
size_t n; |
size_t n; |
char *lp = linep; |
char *lp = linep; |
|
int i = 0; |
|
|
n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); |
n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); |
lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); |
lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); |
if (ip->pad) { |
if (ip->pad) |
n = snprintf(lp, line + sizeof(line) - lp, ip->format, ""); |
while (i++ < ip->minwidth && lp + 1 < line + sizeof(line)) |
if (n > 0) |
*lp++ = ' '; |
lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); |
*lp = '\0'; |
} |
|
return (lp); |
return (lp); |
} |
} |
|
|
|
|
char *p; |
char *p; |
char *lp = linep; |
char *lp = linep; |
char *end = s + BUFSIZ - 1; |
char *end = s + BUFSIZ - 1; |
int c; |
int c, width; |
|
|
if (ip->eof) |
if (ip->eof) |
return (pad(ip)); |
return (pad(ip)); |
|
|
numfiles++; |
numfiles++; |
n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); |
n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); |
lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); |
lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); |
n = snprintf(lp, line + sizeof(line) - lp, ip->format, s); |
width = mbswidth_truncate(s, ip->maxwidth); |
if (n > 0) |
if (ip->align != '-') |
lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); |
while (width++ < ip->minwidth && lp + 1 < line + sizeof(line)) |
|
*lp++ = ip->align; |
|
n = strlcpy(lp, s, line + sizeof(line) - lp); |
|
lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); |
|
if (ip->align == '-') |
|
while (width++ < ip->minwidth && lp + 1 < line + sizeof(line)) |
|
*lp++ = ' '; |
|
*lp = '\0'; |
return (lp); |
return (lp); |
} |
} |
|
|