diff options
Diffstat (limited to 'src/usr.bin/lam/lam.c')
-rw-r--r-- | src/usr.bin/lam/lam.c | 83 |
1 files changed, 57 insertions, 26 deletions
diff --git a/src/usr.bin/lam/lam.c b/src/usr.bin/lam/lam.c index 0554393..df1faf1 100644 --- a/src/usr.bin/lam/lam.c +++ b/src/usr.bin/lam/lam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lam.c,v 1.21 2018/07/11 11:42:17 schwarze Exp $ */ +/* $OpenBSD: lam.c,v 1.22 2018/07/29 11:27:14 schwarze Exp $ */ /* $NetBSD: lam.c,v 1.2 1994/11/14 20:27:42 jtc Exp $ */ /*- @@ -39,6 +39,7 @@ #include <ctype.h> #include <err.h> +#include <locale.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -48,11 +49,13 @@ struct openfile { /* open file structure */ FILE *fp; /* file pointer */ + int minwidth; /* pad this column to this width */ + int maxwidth; /* truncate this column */ short eof; /* eof flag */ short pad; /* pad flag for missing columns */ char eol; /* end of line character */ + char align; /* '0' for zero fill, '-' for left align */ 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. */ #define INPUTSIZE sizeof(input) / sizeof(*input) @@ -61,6 +64,8 @@ int nofinalnl; /* normally append \n to each output line */ char line[BIGBUFSIZ]; char *linep; +int mbswidth_truncate(char *, int); /* utf8.c */ + void usage(void); char *gatherline(struct openfile *); void getargs(int, char *[]); @@ -71,6 +76,8 @@ main(int argc, char *argv[]) { int i; + setlocale(LC_CTYPE, ""); + if (pledge("stdio rpath", NULL) == -1) err(1, "pledge"); @@ -106,9 +113,9 @@ void getargs(int argc, char *argv[]) { struct openfile *ip = input; - char *p; + const char *errstr; + char *p, *q; int ch, P, S, F, T; - size_t siz; P = S = F = T = 0; /* capitalized options */ while (optind < argc) { @@ -120,17 +127,28 @@ getargs(int argc, char *argv[]) case 'F': case 'f': F = (ch == 'F'); /* Validate format string argument. */ - for (p = optarg; *p != '\0'; p++) - if (!isdigit((unsigned char)*p) && - *p != '.' && *p != '-') - errx(1, "%s: invalid width specified", - optarg); - /* '%' + width + 's' + '\0' */ - siz = p - optarg + 3; - if ((p = realloc(ip->format, siz)) == NULL) - err(1, NULL); - snprintf(p, siz, "%%%ss", optarg); - ip->format = p; + p = optarg; + if (*p == '0' || *p == '-') + ip->align = *p++; + else + ip->align = ' '; + if ((q = strchr(p, '.')) != NULL) + *q++ = '\0'; + if (*p != '\0') { + ip->minwidth = strtonum(p, 1, INT_MAX, + &errstr); + 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; case 'S': case 's': S = (ch == 'S'); @@ -157,10 +175,16 @@ getargs(int argc, char *argv[]) ip->pad = P; if (ip->sepstring == NULL) ip->sepstring = S ? (ip-1)->sepstring : ""; - if (ip->format == NULL) - ip->format = (P || F) ? (ip-1)->format : "%s"; if (ip->eol == '\0') 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++; optind++; break; @@ -179,14 +203,14 @@ pad(struct openfile *ip) { size_t n; char *lp = linep; + int i = 0; n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); - if (ip->pad) { - n = snprintf(lp, line + sizeof(line) - lp, ip->format, ""); - if (n > 0) - lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); - } + if (ip->pad) + while (i++ < ip->minwidth && lp + 1 < line + sizeof(line)) + *lp++ = ' '; + *lp = '\0'; return (lp); } @@ -202,7 +226,7 @@ gatherline(struct openfile *ip) char *p; char *lp = linep; char *end = s + BUFSIZ - 1; - int c; + int c, width; if (ip->eof) return (pad(ip)); @@ -220,9 +244,16 @@ gatherline(struct openfile *ip) numfiles++; n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp); lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); - n = snprintf(lp, line + sizeof(line) - lp, ip->format, s); - if (n > 0) - lp += (n < line + sizeof(line) - lp) ? n : strlen(lp); + width = mbswidth_truncate(s, ip->maxwidth); + if (ip->align != '-') + 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); } |