diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-05-21 21:37:12 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-05-21 21:37:12 +0000 |
commit | e1341252a0e5d7d2b7d3d4b0788b708767f5998d (patch) | |
tree | a02cca9f8d377108bc908df11bd73f889967c515 /usr.bin/rs | |
parent | d4e562903dadbc671c7cc5e07d3aa48c7a131c15 (diff) |
avoid divide-by-zero trap when specifying small widths
do not overrun entry array when printing output tables
cleanup storage allocation for entries
use err/warn etc.
Diffstat (limited to 'usr.bin/rs')
-rw-r--r-- | usr.bin/rs/rs.1 | 2 | ||||
-rw-r--r-- | usr.bin/rs/rs.c | 91 |
2 files changed, 48 insertions, 45 deletions
diff --git a/usr.bin/rs/rs.1 b/usr.bin/rs/rs.1 index 07de48c50d6..9916b667247 100644 --- a/usr.bin/rs/rs.1 +++ b/usr.bin/rs/rs.1 @@ -122,6 +122,8 @@ The width of the display, normally 80, is taken to be the positive integer \fIN\fP. .IP \fB\-m\fR Do not trim excess delimiters from the ends of the output array. +.IP \fB\-z\fR +Adapt column widths to fit the largest entries appearing in them. .PP With no arguments, .I rs diff --git a/usr.bin/rs/rs.c b/usr.bin/rs/rs.c index 7112a861522..9e55e126d34 100644 --- a/usr.bin/rs/rs.c +++ b/usr.bin/rs/rs.c @@ -89,7 +89,7 @@ int propgutter; char isep = ' ', osep = ' '; int owidth = 80, gutter = 2; -void error __P((char *, char *)); +void usage __P((char *, char *)); void getargs __P((int, char *[])); void getfile __P((void)); int getline __P((void)); @@ -100,6 +100,11 @@ void prepfile __P((void)); void prints __P((char *, int)); void putfile __P((void)); +#define INCR(ep) do { \ + if (++ep >= endelem) \ + ep = getptrs(ep); \ +} while(0) + int main(argc, argv) int argc; @@ -148,7 +153,8 @@ getfile() p = curline; do { if (flags & ONEPERLINE) { - *ep++ = curline; + *ep = curline; + INCR(ep); /* prepare for next entry */ if (maxlen < curlen) maxlen = curlen; irows++; @@ -166,16 +172,16 @@ getfile() *p = '\0'; /* mark end of entry */ if (maxlen < p - *ep) /* update maxlen */ maxlen = p - *ep; - ep++; /* prepare for next entry */ + INCR(ep); /* prepare for next entry */ } irows++; /* update row count */ if (nullpad) { /* pad missing entries */ padto = elem + irows * icols; - while (ep < padto) - *ep++ = ""; + while (ep < padto) { + *ep = ""; + INCR(ep); + } } - if (ep > endelem) /* if low on pointers */ - ep = getptrs(ep); /* get some more */ } while (getline() != EOF); *ep = 0; /* mark end of pointers */ nelem = ep - elem; @@ -185,21 +191,25 @@ void putfile() { register char **ep; - register int i, j; + register int i, j, n; ep = elem; - if (flags & TRANSPOSE) + if (flags & TRANSPOSE) { for (i = 0; i < orows; i++) { for (j = i; j < nelem; j += orows) prints(ep[j], (j - i) / orows); putchar('\n'); } - else - for (i = 0; i < orows; i++) { - for (j = 0; j < ocols; j++) + } else { + for (n = 0, i = 0; i < orows && n < nelem; i++) { + for (j = 0; j < ocols; j++) { + if (n++ >= nelem) + break; prints(*ep++, j); + } putchar('\n'); } + } } void @@ -223,13 +233,12 @@ prints(s, col) } void -error(msg, s) +usage(msg, s) char *msg, *s; { - fprintf(stderr, "rs: "); - fprintf(stderr, msg, s); + warnx(msg, s); fprintf(stderr, -"\nUsage: rs [ -[csCS][x][kKgGw][N]tTeEnyjhHm ] [ rows [ cols ] ]\n"); +"Usage: rs [ -[csCS][x][kKgGw][N]tTeEnyjhHm ] [ rows [ cols ] ]\n"); exit(1); } @@ -254,8 +263,10 @@ prepfile() } else if (orows == 0 && ocols == 0) { /* decide rows and cols */ ocols = owidth / colw; - if (ocols == 0) - fprintf(stderr, "Display width %d is less than column width %d\n", owidth, colw); + if (ocols == 0) { + warnx("Display width %d is less than column width %d\n", owidth, colw); + ocols = 1; + } if (ocols > nelem) ocols = nelem; orows = nelem / ocols + (nelem % ocols ? 1 : 0); @@ -275,7 +286,7 @@ prepfile() nelem = lp - elem; } if (!(colwidths = (short *) malloc(ocols * sizeof(short)))) - error("malloc: No gutter space", ""); + errx(1, "malloc: No gutter space"); if (flags & SQUEEZE) { if (flags & TRANSPOSE) for (ep = elem, i = 0; i < ocols; i++) { @@ -344,7 +355,7 @@ getline() /* get line; maintain curline, curlen; manage storage */ /*ww = endblock-curline; tt += ww;*/ /*printf("#wasted %d total %d\n",ww,tt);*/ if (!(curline = (char *) malloc(BSIZE))) - error("File too large", ""); + errx(1, "File too large"); endblock = curline + BSIZE; /*printf("#endb %d curline %d\n",endblock,curline);*/ } @@ -360,26 +371,16 @@ char ** getptrs(sp) char **sp; { - register char **p, **ep; + register char **p; - for (;;) { - allocsize += allocsize; - if (!(p = (char **) malloc(allocsize * sizeof(char *)))) { - perror("rs"); - exit(1); - } - if ((endelem = p + allocsize - icols) <= p) { - free(p); - continue; - } - if (elem != 0) - free(elem); - ep = elem; - elem = p; - while (ep < sp) - *p++ = *ep++; - return(p); - } + allocsize += allocsize; + p = (char **)realloc(elem, allocsize * sizeof(char *)); + if (p == (char **)0) + err(1, "no memory"); + + sp += (p - elem); + endelem = (elem = p) + allocsize; + return(sp); } void @@ -419,7 +420,7 @@ getargs(ac, av) case 'w': /* window width, default 80 */ p = getnum(&owidth, p, 0); if (owidth <= 0) - error("Width must be a positive integer", ""); + usage("Width must be a positive integer", ""); break; case 'K': /* skip N lines */ flags |= SKIPPRINT; @@ -475,7 +476,7 @@ getargs(ac, av) p = getlist(&ocbd, p); break; default: - error("Bad flag: %.1s", p); + usage("Bad flag: %.1s", p); } /*if (!osep) osep = isep;*/ @@ -489,7 +490,7 @@ getargs(ac, av) case 0: break; default: - error("Too many arguments. What do you mean by `%s'?", av[3]); + usage("Too many arguments.", ""); } } @@ -503,7 +504,7 @@ getlist(list, p) for (t = p + 1; *t; t++) { if (!isdigit(*t)) - error("Option %.1s requires a list of unsigned numbers separated by commas", t); + usage("Option %.1s requires a list of unsigned numbers separated by commas", t); count++; while (*t && isdigit(*t)) t++; @@ -511,7 +512,7 @@ getlist(list, p) break; } if (!(*list = (short *) malloc(count * sizeof(short)))) - error("No list space", ""); + errx(1, "No list space"); count = 0; for (t = p + 1; *t; t++) { (*list)[count++] = atoi(t); @@ -535,7 +536,7 @@ getnum(num, p, strict) /* num = number p points to; if (strict) complain */ if (!isdigit(*++t)) { if (strict || *t == '-' || *t == '+') - error("Option %.1s requires an unsigned integer", p); + usage("Option %.1s requires an unsigned integer", p); *num = 0; return(p); } |