Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/rs/rs.cc
- This file was moved from usr.bin/rs/rs.c.
Show All 32 Lines | |||||
* rs - reshape a data array | * rs - reshape a data array | ||||
* Author: John Kunze, Office of Comp. Affairs, UCB | * Author: John Kunze, Office of Comp. Affairs, UCB | ||||
* BEWARE: lots of unfinished edges | * BEWARE: lots of unfinished edges | ||||
*/ | */ | ||||
#include <err.h> | #include <err.h> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <limits.h> | #include <limits.h> | ||||
#include <stddef.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <vector> | |||||
static long flags; | static long flags; | ||||
#define TRANSPOSE 000001 | #define TRANSPOSE 000001 | ||||
#define MTRANSPOSE 000002 | #define MTRANSPOSE 000002 | ||||
#define ONEPERLINE 000004 | #define ONEPERLINE 000004 | ||||
#define ONEISEPONLY 000010 | #define ONEISEPONLY 000010 | ||||
#define ONEOSEPONLY 000020 | #define ONEOSEPONLY 000020 | ||||
#define NOTRIMENDCOL 000040 | #define NOTRIMENDCOL 000040 | ||||
#define SQUEEZE 000100 | #define SQUEEZE 000100 | ||||
#define SHAPEONLY 000200 | #define SHAPEONLY 000200 | ||||
#define DETAILSHAPE 000400 | #define DETAILSHAPE 000400 | ||||
#define RIGHTADJUST 001000 | #define RIGHTADJUST 001000 | ||||
#define NULLPAD 002000 | #define NULLPAD 002000 | ||||
#define RECYCLE 004000 | #define RECYCLE 004000 | ||||
#define SKIPPRINT 010000 | #define SKIPPRINT 010000 | ||||
#define ICOLBOUNDS 020000 | #define ICOLBOUNDS 020000 | ||||
#define OCOLBOUNDS 040000 | #define OCOLBOUNDS 040000 | ||||
#define ONEPERCHAR 0100000 | #define ONEPERCHAR 0100000 | ||||
#define NOARGS 0200000 | #define NOARGS 0200000 | ||||
static short *colwidths; | static short *colwidths; | ||||
static short *cord; | static short *cord; | ||||
static short *icbd; | static short *icbd; | ||||
static short *ocbd; | static short *ocbd; | ||||
static int nelem; | static std::vector<char *> elem; | ||||
static char **elem; | |||||
static char **endelem; | |||||
static char *curline; | static char *curline; | ||||
static int allocsize = BUFSIZ; | static size_t curlen; | ||||
static int curlen; | static size_t irows, icols; | ||||
static int irows, icols; | static size_t orows = 0, ocols = 0; | ||||
static int orows = 0, ocols = 0; | static size_t maxlen; | ||||
static int maxlen; | |||||
static int skip; | static int skip; | ||||
static int propgutter; | static int propgutter; | ||||
static char isep = ' ', osep = ' '; | static char isep = ' ', osep = ' '; | ||||
static char blank[] = ""; | static char blank[] = ""; | ||||
static int owidth = 80, gutter = 2; | static int owidth = 80, gutter = 2; | ||||
static void getargs(int, char *[]); | static void getargs(int, char *[]); | ||||
static void getfile(void); | static void getfile(void); | ||||
static int get_line(void); | static int get_line(void); | ||||
static char *getlist(short **, char *); | static char *getlist(short **, char *); | ||||
static char *getnum(int *, char *, int); | static char *getnum(int *, char *, int); | ||||
static char **getptrs(char **); | |||||
static void prepfile(void); | static void prepfile(void); | ||||
static void prints(char *, int); | static void prints(char *, int); | ||||
static void putfile(void); | static void putfile(void); | ||||
static void usage(void); | static void usage(void); | ||||
#define INCR(ep) do { \ | |||||
if (++ep >= endelem) \ | |||||
ep = getptrs(ep); \ | |||||
} while(0) | |||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
getargs(argc, argv); | getargs(argc, argv); | ||||
getfile(); | getfile(); | ||||
if (flags & SHAPEONLY) { | if (flags & SHAPEONLY) { | ||||
printf("%d %d\n", irows, icols); | printf("%zu %zu\n", irows, icols); | ||||
exit(0); | exit(0); | ||||
} | } | ||||
prepfile(); | prepfile(); | ||||
putfile(); | putfile(); | ||||
exit(0); | exit(0); | ||||
} | } | ||||
static void | static void | ||||
getfile(void) | getfile(void) | ||||
{ | { | ||||
char *p, *sp; | char *p, *sp; | ||||
char *endp; | char *endp; | ||||
char **ep; | |||||
int c; | int c; | ||||
int len; | |||||
int multisep = (flags & ONEISEPONLY ? 0 : 1); | int multisep = (flags & ONEISEPONLY ? 0 : 1); | ||||
int nullpad = flags & NULLPAD; | int nullpad = flags & NULLPAD; | ||||
char **padto; | size_t len, padto; | ||||
while (skip--) { | while (skip--) { | ||||
c = get_line(); | c = get_line(); | ||||
if (flags & SKIPPRINT) | if (flags & SKIPPRINT) | ||||
puts(curline); | puts(curline); | ||||
if (c == EOF) | if (c == EOF) | ||||
return; | return; | ||||
} | } | ||||
get_line(); | get_line(); | ||||
if (flags & NOARGS && curlen < owidth) | if (flags & NOARGS && curlen < (size_t)owidth) | ||||
flags |= ONEPERLINE; | flags |= ONEPERLINE; | ||||
if (flags & ONEPERLINE) | if (flags & ONEPERLINE) | ||||
icols = 1; | icols = 1; | ||||
else /* count cols on first line */ | else /* count cols on first line */ | ||||
for (p = curline, endp = curline + curlen; p < endp; p++) { | for (p = curline, endp = curline + curlen; p < endp; p++) { | ||||
if (*p == isep && multisep) | if (*p == isep && multisep) | ||||
continue; | continue; | ||||
icols++; | icols++; | ||||
while (*p && *p != isep) | while (*p && *p != isep) | ||||
p++; | p++; | ||||
} | } | ||||
ep = getptrs(elem); | |||||
do { | do { | ||||
if (flags & ONEPERLINE) { | if (flags & ONEPERLINE) { | ||||
*ep = curline; | elem.push_back(curline); | ||||
INCR(ep); /* prepare for next entry */ | |||||
if (maxlen < curlen) | if (maxlen < curlen) | ||||
maxlen = curlen; | maxlen = curlen; | ||||
irows++; | irows++; | ||||
continue; | continue; | ||||
} | } | ||||
for (p = curline, endp = curline + curlen; p < endp; p++) { | for (p = curline, endp = curline + curlen; p < endp; p++) { | ||||
if (*p == isep && multisep) | if (*p == isep && multisep) | ||||
continue; /* eat up column separators */ | continue; /* eat up column separators */ | ||||
if (*p == isep) /* must be an empty column */ | if (*p == isep) /* must be an empty column */ | ||||
*ep = blank; | elem.push_back(blank); | ||||
else /* store column entry */ | else /* store column entry */ | ||||
*ep = p; | elem.push_back(p); | ||||
sp = p; | sp = p; | ||||
while (p < endp && *p != isep) | while (p < endp && *p != isep) | ||||
p++; /* find end of entry */ | p++; /* find end of entry */ | ||||
*p = '\0'; /* mark end of entry */ | *p = '\0'; /* mark end of entry */ | ||||
len = p - sp; | len = p - sp; | ||||
if (maxlen < len) /* update maxlen */ | if (maxlen < len) /* update maxlen */ | ||||
maxlen = len; | maxlen = len; | ||||
INCR(ep); /* prepare for next entry */ | |||||
} | } | ||||
irows++; /* update row count */ | irows++; /* update row count */ | ||||
if (nullpad) { /* pad missing entries */ | if (nullpad) { /* pad missing entries */ | ||||
padto = elem + irows * icols; | padto = irows * icols; | ||||
while (ep < padto) { | elem.resize(padto, blank); | ||||
*ep = blank; | |||||
INCR(ep); | |||||
} | } | ||||
} | |||||
} while (get_line() != EOF); | } while (get_line() != EOF); | ||||
*ep = 0; /* mark end of pointers */ | |||||
jhb: Nothing seemed to depend on this NULL being present, and `nelem` doesn't include it. | |||||
nelem = ep - elem; | |||||
} | } | ||||
static void | static void | ||||
putfile(void) | putfile(void) | ||||
{ | { | ||||
char **ep; | size_t i, j, k; | ||||
int i, j, k; | |||||
ep = elem; | |||||
if (flags & TRANSPOSE) | if (flags & TRANSPOSE) | ||||
for (i = 0; i < orows; i++) { | for (i = 0; i < orows; i++) { | ||||
for (j = i; j < nelem; j += orows) | for (j = i; j < elem.size(); j += orows) | ||||
prints(ep[j], (j - i) / orows); | prints(elem[j], (j - i) / orows); | ||||
putchar('\n'); | putchar('\n'); | ||||
} | } | ||||
else | else | ||||
for (i = k = 0; i < orows; i++) { | for (i = k = 0; i < orows; i++) { | ||||
for (j = 0; j < ocols; j++, k++) | for (j = 0; j < ocols; j++, k++) | ||||
if (k < nelem) | if (k < elem.size()) | ||||
prints(ep[k], j); | prints(elem[k], j); | ||||
putchar('\n'); | putchar('\n'); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
prints(char *s, int col) | prints(char *s, int col) | ||||
{ | { | ||||
int n; | int n; | ||||
Show All 17 Lines | usage(void) | ||||
fprintf(stderr, | fprintf(stderr, | ||||
"usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n"); | "usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
static void | static void | ||||
prepfile(void) | prepfile(void) | ||||
{ | { | ||||
char **ep; | size_t i, j; | ||||
int i; | size_t colw, max, n, orig_size, padto; | ||||
int j; | |||||
char **lp; | |||||
int colw; | |||||
int max; | |||||
int n; | |||||
if (!nelem) | if (elem.empty()) | ||||
exit(0); | exit(0); | ||||
gutter += maxlen * propgutter / 100.0; | gutter += maxlen * propgutter / 100.0; | ||||
colw = maxlen + gutter; | colw = maxlen + gutter; | ||||
if (flags & MTRANSPOSE) { | if (flags & MTRANSPOSE) { | ||||
orows = icols; | orows = icols; | ||||
ocols = irows; | ocols = irows; | ||||
} | } | ||||
else if (orows == 0 && ocols == 0) { /* decide rows and cols */ | else if (orows == 0 && ocols == 0) { /* decide rows and cols */ | ||||
ocols = owidth / colw; | ocols = owidth / colw; | ||||
if (ocols == 0) { | if (ocols == 0) { | ||||
warnx("display width %d is less than column width %d", | warnx("display width %d is less than column width %zu", | ||||
owidth, colw); | owidth, colw); | ||||
ocols = 1; | ocols = 1; | ||||
} | } | ||||
if (ocols > nelem) | if (ocols > elem.size()) | ||||
ocols = nelem; | ocols = elem.size(); | ||||
orows = nelem / ocols + (nelem % ocols ? 1 : 0); | orows = elem.size() / ocols + (elem.size() % ocols ? 1 : 0); | ||||
} | } | ||||
else if (orows == 0) /* decide on rows */ | else if (orows == 0) /* decide on rows */ | ||||
orows = nelem / ocols + (nelem % ocols ? 1 : 0); | orows = elem.size() / ocols + (elem.size() % ocols ? 1 : 0); | ||||
else if (ocols == 0) /* decide on cols */ | else if (ocols == 0) /* decide on cols */ | ||||
ocols = nelem / orows + (nelem % orows ? 1 : 0); | ocols = elem.size() / orows + (elem.size() % orows ? 1 : 0); | ||||
lp = elem + orows * ocols; | padto = orows * ocols; | ||||
while (lp > endelem) { | orig_size = elem.size(); | ||||
getptrs(elem + nelem); | |||||
lp = elem + orows * ocols; | |||||
} | |||||
if (flags & RECYCLE) { | if (flags & RECYCLE) { | ||||
for (ep = elem + nelem; ep < lp; ep++) | for (i = 0; elem.size() < padto; i++) | ||||
*ep = *(ep - nelem); | elem.push_back(elem[i % orig_size]); | ||||
nelem = lp - elem; | |||||
} | } | ||||
if (!(colwidths = (short *) malloc(ocols * sizeof(short)))) | if (!(colwidths = (short *) malloc(ocols * sizeof(short)))) | ||||
errx(1, "malloc"); | errx(1, "malloc"); | ||||
if (flags & SQUEEZE) { | if (flags & SQUEEZE) { | ||||
ep = elem; | if (flags & TRANSPOSE) { | ||||
if (flags & TRANSPOSE) | auto it = elem.begin(); | ||||
for (i = 0; i < ocols; i++) { | for (i = 0; i < ocols; i++) { | ||||
max = 0; | max = 0; | ||||
for (j = 0; *ep != NULL && j < orows; j++) | for (j = 0; it != elem.end() && j < orows; j++) | ||||
if ((n = strlen(*ep++)) > max) | if ((n = strlen(*it++)) > max) | ||||
max = n; | max = n; | ||||
colwidths[i] = max + gutter; | colwidths[i] = max + gutter; | ||||
} | } | ||||
else | } else { | ||||
for (i = 0; i < ocols; i++) { | for (i = 0; i < ocols; i++) { | ||||
max = 0; | max = 0; | ||||
for (j = i; j < nelem; j += ocols) | for (j = i; j < elem.size(); j += ocols) | ||||
if ((n = strlen(ep[j])) > max) | if ((n = strlen(elem[j])) > max) | ||||
max = n; | max = n; | ||||
colwidths[i] = max + gutter; | colwidths[i] = max + gutter; | ||||
} | } | ||||
} | } | ||||
} | |||||
/* for (i = 0; i < orows; i++) { | /* for (i = 0; i < orows; i++) { | ||||
for (j = i; j < nelem; j += orows) | for (j = i; j < elem.size(); j += orows) | ||||
prints(ep[j], (j - i) / orows); | prints(elem[j], (j - i) / orows); | ||||
putchar('\n'); | putchar('\n'); | ||||
} | } | ||||
else | else { | ||||
auto it = elem.begin(); | |||||
for (i = 0; i < orows; i++) { | for (i = 0; i < orows; i++) { | ||||
for (j = 0; j < ocols; j++) | for (j = 0; j < ocols; j++) | ||||
prints(*ep++, j); | prints(*it++, j); | ||||
putchar('\n'); | putchar('\n'); | ||||
}*/ | }*/ | ||||
else | else | ||||
for (i = 0; i < ocols; i++) | for (i = 0; i < ocols; i++) | ||||
colwidths[i] = colw; | colwidths[i] = colw; | ||||
if (!(flags & NOTRIMENDCOL)) { | if (!(flags & NOTRIMENDCOL)) { | ||||
if (flags & RIGHTADJUST) | if (flags & RIGHTADJUST) | ||||
colwidths[0] -= gutter; | colwidths[0] -= gutter; | ||||
else | else | ||||
colwidths[ocols - 1] = 0; | colwidths[ocols - 1] = 0; | ||||
} | } | ||||
n = orows * ocols; | |||||
Done Inline ActionsThis seems like dead code. At line 280 above in the old code we set nelem to n above. The only way we wouldn't execute that line was if lp already fit which would imply that nelem was greater than orows * ocols on function entry. Either way, nelem would never be larger than n if the RECYCLE flag was set. jhb: This seems like dead code. At line 280 above in the old code we set `nelem` to `n` above. The… | |||||
if (n > nelem && (flags & RECYCLE)) | |||||
nelem = n; | |||||
/*for (i = 0; i < ocols; i++) | /*for (i = 0; i < ocols; i++) | ||||
warnx("%d is colwidths, nelem %d", colwidths[i], nelem);*/ | warnx("%d is colwidths, nelem %zu", colwidths[i], elem.size());*/ | ||||
} | } | ||||
#define BSIZE (LINE_MAX * 2) | #define BSIZE (LINE_MAX * 2) | ||||
static char ibuf[BSIZE]; | static char ibuf[BSIZE]; | ||||
static int | static int | ||||
get_line(void) /* get line; maintain curline, curlen; manage storage */ | get_line(void) /* get line; maintain curline, curlen; manage storage */ | ||||
{ | { | ||||
static int putlength; | static int putlength; | ||||
static char *endblock = ibuf + BSIZE; | static char *endblock = ibuf + BSIZE; | ||||
char *p; | char *p; | ||||
int c, i; | int c, i; | ||||
if (!irows) { | if (irows == 0) { | ||||
curline = ibuf; | curline = ibuf; | ||||
putlength = flags & DETAILSHAPE; | putlength = flags & DETAILSHAPE; | ||||
} | } | ||||
else if (skip <= 0) { /* don't waste storage */ | else if (skip <= 0) { /* don't waste storage */ | ||||
curline += curlen + 1; | curline += curlen + 1; | ||||
if (putlength) { /* print length, recycle storage */ | if (putlength) { /* print length, recycle storage */ | ||||
printf(" %d line %d\n", curlen, irows); | printf(" %zu line %zu\n", curlen, irows); | ||||
curline = ibuf; | curline = ibuf; | ||||
} | } | ||||
} | } | ||||
if (!putlength && endblock - curline < LINE_MAX + 1) { /* need storage */ | if (!putlength && endblock - curline < LINE_MAX + 1) { /* need storage */ | ||||
/*ww = endblock-curline; tt += ww;*/ | /*ww = endblock-curline; tt += ww;*/ | ||||
/*printf("#wasted %d total %d\n",ww,tt);*/ | /*printf("#wasted %d total %d\n",ww,tt);*/ | ||||
if (!(curline = (char *) malloc(BSIZE))) | if (!(curline = (char *) malloc(BSIZE))) | ||||
errx(1, "file too large"); | errx(1, "file too large"); | ||||
endblock = curline + BSIZE; | endblock = curline + BSIZE; | ||||
/*printf("#endb %d curline %d\n",endblock,curline);*/ | /*printf("#endb %d curline %d\n",endblock,curline);*/ | ||||
} | } | ||||
for (p = curline, i = 0;; *p++ = c, i++) { | for (p = curline, i = 0;; *p++ = c, i++) { | ||||
if ((c = getchar()) == EOF) | if ((c = getchar()) == EOF) | ||||
break; | break; | ||||
if (i >= LINE_MAX) | if (i >= LINE_MAX) | ||||
errx(1, "maximum line length (%d) exceeded", LINE_MAX); | errx(1, "maximum line length (%d) exceeded", LINE_MAX); | ||||
if (c == '\n') | if (c == '\n') | ||||
break; | break; | ||||
} | } | ||||
*p = '\0'; | *p = '\0'; | ||||
curlen = i; | curlen = i; | ||||
return(c); | return(c); | ||||
} | } | ||||
static char ** | |||||
getptrs(char **sp) | |||||
{ | |||||
char **p; | |||||
ptrdiff_t offset; | |||||
offset = sp - elem; | |||||
allocsize += allocsize; | |||||
p = (char **)realloc(elem, allocsize * sizeof(char *)); | |||||
if (p == NULL) | |||||
err(1, "no memory"); | |||||
sp = p + offset; | |||||
endelem = (elem = p) + allocsize; | |||||
return(sp); | |||||
} | |||||
static void | static void | ||||
getargs(int ac, char *av[]) | getargs(int ac, char *av[]) | ||||
{ | { | ||||
long val; | |||||
char *p; | char *p; | ||||
if (ac == 1) { | if (ac == 1) { | ||||
flags |= NOARGS | TRANSPOSE; | flags |= NOARGS | TRANSPOSE; | ||||
} | } | ||||
while (--ac && **++av == '-') | while (--ac && **++av == '-') | ||||
for (p = *av+1; *p; p++) | for (p = *av+1; *p; p++) | ||||
switch (*p) { | switch (*p) { | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | /*if (!osep) | ||||
osep = isep;*/ | osep = isep;*/ | ||||
switch (ac) { | switch (ac) { | ||||
#if 0 | #if 0 | ||||
case 3: | case 3: | ||||
opages = atoi(av[2]); | opages = atoi(av[2]); | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
#endif | #endif | ||||
case 2: | case 2: | ||||
if ((ocols = atoi(av[1])) < 0) | val = strtol(av[1], NULL, 10); | ||||
ocols = 0; | if (val >= 0) | ||||
ocols = val; | |||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case 1: | case 1: | ||||
if ((orows = atoi(av[0])) < 0) | val = strtol(av[0], NULL, 10); | ||||
orows = 0; | if (val >= 0) | ||||
orows = val; | |||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case 0: | case 0: | ||||
break; | break; | ||||
default: | default: | ||||
errx(1, "too many arguments"); | errx(1, "too many arguments"); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 53 Lines • Show Last 20 Lines |
Nothing seemed to depend on this NULL being present, and nelem doesn't include it.