113852Ssam /* Copyright (c) 1983 Regents of the University of California */ 213852Ssam 313852Ssam #ifndef lint 4*16036Sjak static char sccsid[] = "@(#)rs.c 4.2 (Berkeley) 02/11/84"; 513852Ssam #endif not lint 613852Ssam 713852Ssam /* 813852Ssam * rs - reshape a data array 913852Ssam * Author: John Kunze, Office of Comp. Affairs, UCB 1013852Ssam * BEWARE: lots of unfinished edges 1113852Ssam */ 1213852Ssam 1313852Ssam #include <stdio.h> 1413852Ssam #include <ctype.h> 1513852Ssam 1613852Ssam long flags; 1713852Ssam #define TRANSPOSE 000001 1813852Ssam #define MTRANSPOSE 000002 1913852Ssam #define ONEPERLINE 000004 2013852Ssam #define ONEISEPONLY 000010 2113852Ssam #define ONEOSEPONLY 000020 2213852Ssam #define NOTRIMENDCOL 000040 2313852Ssam #define SQUEEZE 000100 2413852Ssam #define SHAPEONLY 000200 2513852Ssam #define DETAILSHAPE 000400 2613852Ssam #define RIGHTADJUST 001000 2713852Ssam #define NULLPAD 002000 2813852Ssam #define RECYCLE 004000 2913852Ssam #define SKIPPRINT 010000 3013852Ssam #define ICOLBOUNDS 020000 3113852Ssam #define OCOLBOUNDS 040000 3213852Ssam #define ONEPERCHAR 0100000 33*16036Sjak #define NOARGS 0200000 3413852Ssam 3513852Ssam char buf[BUFSIZ]; 3613852Ssam short *colwidths; 3713852Ssam short *cord; 3813852Ssam short *icbd; 3913852Ssam short *ocbd; 4013852Ssam int nelem; 4113852Ssam char **elem; 4213852Ssam char **endelem; 4313852Ssam char *curline; 4413852Ssam int allocsize = BUFSIZ; 4513852Ssam int curlen; 4613852Ssam int irows, icols; 4713852Ssam int orows, ocols; 4813852Ssam int maxlen; 4913852Ssam int skip; 5013852Ssam int propgutter; 5113852Ssam char isep = ' ', osep = ' '; 5213852Ssam int owidth = 80, gutter = 2; 5313852Ssam 5413852Ssam char **getptrs(); 5513852Ssam 5613852Ssam main(argc, argv) 5713852Ssam int argc; 5813852Ssam char **argv; 5913852Ssam { 6013852Ssam setbuf(stdout, buf); 6113852Ssam getargs(argc, argv); 6213852Ssam getfile(); 6313852Ssam if (flags & SHAPEONLY) { 6413852Ssam printf("%d %d\n", irows, icols); 6513852Ssam exit(0); 6613852Ssam } 6713852Ssam prepfile(); 6813852Ssam /*fprintf(stderr, "#irows %d icols %d orows %d ocols %d\n",irows,icols,orows,ocols);*/ 6913852Ssam putfile(); 7013852Ssam } 7113852Ssam 7213852Ssam getfile() 7313852Ssam { 7413852Ssam register char *p; 7513852Ssam register char *endp; 7613852Ssam register char **ep = 0; 7713852Ssam int multisep = (flags & ONEISEPONLY ? 0 : 1); 7813852Ssam int nullpad = flags & NULLPAD; 7913852Ssam char **padto; 8013852Ssam 8113852Ssam while (skip--) { 8213852Ssam getline(); 8313852Ssam if (flags & SKIPPRINT) 8413852Ssam puts(curline); 8513852Ssam } 8613852Ssam getline(); 87*16036Sjak if (flags & NOARGS && curlen < owidth) 88*16036Sjak flags |= ONEPERLINE; 8913852Ssam if (flags & ONEPERLINE) 9013852Ssam icols = 1; 9113852Ssam else /* count cols on first line */ 9213852Ssam for (p = curline, endp = curline + curlen; p < endp; p++) { 9313852Ssam if (*p == isep && multisep) 9413852Ssam continue; 9513852Ssam icols++; 9613852Ssam while (*p && *p != isep) 9713852Ssam p++; 9813852Ssam } 9913852Ssam ep = getptrs(elem); 10013852Ssam p = curline; 10113852Ssam do { 10213852Ssam if (flags & ONEPERLINE) { 10313852Ssam *ep++ = curline; 10413852Ssam if (maxlen < curlen) 10513852Ssam maxlen = curlen; 10613852Ssam irows++; 10713852Ssam continue; 10813852Ssam } 10913852Ssam for (p = curline, endp = curline + curlen; p < endp; p++) { 11013852Ssam if (*p == isep && multisep) 11113852Ssam continue; /* eat up column separators */ 11213852Ssam if (*p == isep) /* must be an empty column */ 11313852Ssam *ep = ""; 11413852Ssam else /* store column entry */ 11513852Ssam *ep = p; 11613852Ssam while (p < endp && *p != isep) 11713852Ssam p++; /* find end of entry */ 11813852Ssam *p = '\0'; /* mark end of entry */ 11913852Ssam if (maxlen < p - *ep) /* update maxlen */ 12013852Ssam maxlen = p - *ep; 12113852Ssam ep++; /* prepare for next entry */ 12213852Ssam } 12313852Ssam irows++; /* update row count */ 12413852Ssam if (nullpad) { /* pad missing entries */ 12513852Ssam padto = elem + irows * icols; 12613852Ssam while (ep < padto) 12713852Ssam *ep++ = ""; 12813852Ssam } 12913852Ssam if (ep > endelem) /* if low on pointers */ 13013852Ssam ep = getptrs(ep); /* get some more */ 13113852Ssam } while (getline() != EOF); 13213852Ssam *ep = 0; /* mark end of pointers */ 13313852Ssam nelem = ep - elem; 13413852Ssam } 13513852Ssam 13613852Ssam putfile() 13713852Ssam { 13813852Ssam register char **ep; 13913852Ssam register int i; 14013852Ssam register int j; 14113852Ssam 14213852Ssam ep = elem; 14313852Ssam if (flags & TRANSPOSE) 14413852Ssam for (i = 0; i < orows; i++) { 14513852Ssam for (j = i; j < nelem; j += orows) 14613852Ssam prints(ep[j], (j - i) / orows); 14713852Ssam putchar('\n'); 14813852Ssam } 14913852Ssam else 15013852Ssam for (i = 0; i < orows; i++) { 15113852Ssam for (j = 0; j < ocols; j++) 15213852Ssam prints(*ep++, j); 15313852Ssam putchar('\n'); 15413852Ssam } 15513852Ssam } 15613852Ssam 15713852Ssam prints(s, col) 15813852Ssam char *s; 15913852Ssam int col; 16013852Ssam { 16113852Ssam register char *p = s; 16213852Ssam register int n; 16313852Ssam 16413852Ssam while (*p) 16513852Ssam p++; 16613852Ssam n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s)); 16713852Ssam if (flags & RIGHTADJUST) 16813852Ssam while (n-- > 0) 16913852Ssam putchar(osep); 17013852Ssam for (p = s; *p; p++) 17113852Ssam putchar(*p); 17213852Ssam while (n-- > 0) 17313852Ssam putchar(osep); 17413852Ssam } 17513852Ssam 17613852Ssam error(msg, s) 17713852Ssam char *msg; 17813852Ssam char *s; 17913852Ssam { 18013852Ssam fprintf(stderr, "rs: "); 18113852Ssam fprintf(stderr, msg, s); 18213852Ssam fprintf(stderr, "\nUsage: rs [ -[csCS][x][kKgGw][N]tTeEnyjhHm ] [ rows [ cols ] ]\n"); 18313852Ssam exit(1); 18413852Ssam } 18513852Ssam 18613852Ssam prepfile() 18713852Ssam { 18813852Ssam register char **ep; 18913852Ssam register int i; 19013852Ssam register int j; 19113852Ssam char **lp; 19213852Ssam int colw; 19313852Ssam int max = 0; 19413852Ssam int n; 19513852Ssam 19613852Ssam if (!nelem) 19713852Ssam exit(0); 19813852Ssam gutter += maxlen * propgutter / 100.0; 19913852Ssam colw = maxlen + gutter; 20013852Ssam if (flags & MTRANSPOSE) { 20113852Ssam orows = icols; 20213852Ssam ocols = irows; 20313852Ssam } 20413852Ssam else if (orows == 0 && ocols == 0) { /* decide rows and cols */ 205*16036Sjak ocols = owidth / colw; 206*16036Sjak if (ocols == 0) 207*16036Sjak fprintf(stderr, "Display width %d is less than column width %d\n", owidth, colw); 20813852Ssam if (ocols > nelem) 20913852Ssam ocols = nelem; 21013852Ssam orows = nelem / ocols + (nelem % ocols ? 1 : 0); 21113852Ssam } 21213852Ssam else if (orows == 0) /* decide on rows */ 21313852Ssam orows = nelem / ocols + (nelem % ocols ? 1 : 0); 21413852Ssam else if (ocols == 0) /* decide on cols */ 21513852Ssam ocols = nelem / orows + (nelem % orows ? 1 : 0); 21613852Ssam lp = elem + orows * ocols; 21713852Ssam while (lp > endelem) { 21813852Ssam getptrs(elem + nelem); 21913852Ssam lp = elem + orows * ocols; 22013852Ssam } 22113852Ssam if (flags & RECYCLE) { 22213852Ssam for (ep = elem + nelem; ep < lp; ep++) 22313852Ssam *ep = *(ep - nelem); 22413852Ssam nelem = lp - elem; 22513852Ssam } 22613852Ssam if (!(colwidths = (short *) malloc(ocols * sizeof(short)))) 22713852Ssam error("malloc: No gutter space", ""); 22813852Ssam if (flags & SQUEEZE) { 22913852Ssam if (flags & TRANSPOSE) 23013852Ssam for (ep = elem, i = 0; i < ocols; i++) { 23113852Ssam for (j = 0; j < orows; j++) 23213852Ssam if ((n = strlen(*ep++)) > max) 23313852Ssam max = n; 23413852Ssam colwidths[i] = max + gutter; 23513852Ssam } 23613852Ssam else 23713852Ssam for (i = 0; i < ocols; i++) { 23813852Ssam for (j = i; j < nelem; j += ocols) 23913852Ssam if ((n = strlen(ep[j])) > max) 24013852Ssam max = n; 24113852Ssam colwidths[i] = max + gutter; 24213852Ssam } 24313852Ssam } 24413852Ssam /* for (i = 0; i < orows; i++) { 24513852Ssam for (j = i; j < nelem; j += orows) 24613852Ssam prints(ep[j], (j - i) / orows); 24713852Ssam putchar('\n'); 24813852Ssam } 24913852Ssam else 25013852Ssam for (i = 0; i < orows; i++) { 25113852Ssam for (j = 0; j < ocols; j++) 25213852Ssam prints(*ep++, j); 25313852Ssam putchar('\n'); 25413852Ssam }*/ 25513852Ssam else 25613852Ssam for (i = 0; i < ocols; i++) 25713852Ssam colwidths[i] = colw; 25813852Ssam if (!(flags & NOTRIMENDCOL)) { 25913852Ssam if (flags & RIGHTADJUST) 26013852Ssam colwidths[0] -= gutter; 26113852Ssam else 26213852Ssam colwidths[ocols - 1] = 0; 26313852Ssam } 26413852Ssam n = orows * ocols; 26513852Ssam if (n > nelem && (flags & RECYCLE)) 26613852Ssam nelem = n; 26713852Ssam /*for (i = 0; i < ocols; i++) 26813852Ssam fprintf(stderr, "%d ",colwidths[i]); 26913852Ssam fprintf(stderr, "is colwidths, nelem %d\n", nelem);*/ 27013852Ssam } 27113852Ssam 27213852Ssam #define BSIZE 2048 27313852Ssam char ibuf[BSIZE]; /* two screenfuls should do */ 27413852Ssam 27513852Ssam getline() /* get line; maintain curline, curlen; manage storage */ 27613852Ssam { 27713852Ssam register char *p; 27813852Ssam register int c; 27913852Ssam register int i; 28013852Ssam static int putlength; 28113852Ssam static char *endblock = ibuf + BSIZE; 28213852Ssam 28313852Ssam if (!irows) { 28413852Ssam curline = ibuf; 28513852Ssam putlength = flags & DETAILSHAPE; 28613852Ssam } 28713852Ssam else if (skip <= 0) { /* don't waste storage */ 28813852Ssam curline += curlen + 1; 28913852Ssam if (putlength) /* print length, recycle storage */ 29013852Ssam printf(" %d line %d\n", curlen, irows); 29113852Ssam } 29213852Ssam if (!putlength && endblock - curline < BUFSIZ) { /* need storage */ 29313852Ssam /*ww = endblock-curline; tt += ww;*/ 29413852Ssam /*printf("#wasted %d total %d\n",ww,tt);*/ 29513852Ssam if (!(curline = (char *) malloc(BSIZE))) 29613852Ssam error("File too large", ""); 29713852Ssam endblock = curline + BSIZE; 29813852Ssam /*printf("#endb %d curline %d\n",endblock,curline);*/ 29913852Ssam } 30013852Ssam for (p = curline, i = 1; i < BUFSIZ; *p++ = c, i++) 30113852Ssam if ((c = getchar()) == EOF || c == '\n') 30213852Ssam break; 30313852Ssam *p = '\0'; 30413852Ssam curlen = i - 1; 30513852Ssam return(c); 30613852Ssam } 30713852Ssam 30813852Ssam char ** 30913852Ssam getptrs(sp) 31013852Ssam char **sp; 31113852Ssam { 31213852Ssam register char **p; 31313852Ssam register char **ep; 31413852Ssam 31513852Ssam for (;;) { 31613852Ssam allocsize += allocsize; 31713852Ssam if (!(p = (char **) malloc(allocsize * sizeof(char *)))) { 31813852Ssam perror("rs"); 31913852Ssam exit(1); 32013852Ssam } 32113852Ssam if ((endelem = p + allocsize - icols) <= p) { 32213852Ssam free(p); 32313852Ssam continue; 32413852Ssam } 32513852Ssam if (elem != 0) 32613852Ssam free(elem); 32713852Ssam ep = elem; 32813852Ssam elem = p; 32913852Ssam while (ep < sp) 33013852Ssam *p++ = *ep++; 33113852Ssam return(p); 33213852Ssam } 33313852Ssam } 33413852Ssam 33513852Ssam getargs(ac, av) 33613852Ssam int ac; 33713852Ssam char **av; 33813852Ssam { 33913852Ssam register char *p; 34013852Ssam char *getnum(), *getlist(); 34113852Ssam 34213852Ssam if (ac == 1) { 343*16036Sjak flags |= NOARGS | TRANSPOSE; 34413852Ssam } 34513852Ssam while (--ac && **++av == '-') 34613852Ssam for (p = *av+1; *p; p++) 34713852Ssam switch (*p) { 34813852Ssam case 'T': 34913852Ssam flags |= MTRANSPOSE; 35013852Ssam case 't': 35113852Ssam flags |= TRANSPOSE; 35213852Ssam break; 35313852Ssam case 'c': /* input col. separator */ 35413852Ssam flags |= ONEISEPONLY; 35513852Ssam case 's': /* one or more allowed */ 35613852Ssam if (p[1]) 35713852Ssam isep = *++p; 35813852Ssam else 35913852Ssam isep = '\t'; /* default is ^I */ 36013852Ssam break; 36113852Ssam case 'C': 36213852Ssam flags |= ONEOSEPONLY; 36313852Ssam case 'S': 36413852Ssam if (p[1]) 36513852Ssam osep = *++p; 36613852Ssam else 36713852Ssam osep = '\t'; /* default is ^I */ 36813852Ssam break; 36913852Ssam case 'w': /* window width, default 80 */ 37013852Ssam p = getnum(&owidth, p, 0); 37113852Ssam if (owidth <= 0) 37213852Ssam error("Width must be a positive integer", ""); 37313852Ssam break; 37413852Ssam case 'K': /* skip N lines */ 37513852Ssam flags |= SKIPPRINT; 37613852Ssam case 'k': /* skip, do not print */ 37713852Ssam p = getnum(&skip, p, 0); 37813852Ssam if (!skip) 37913852Ssam skip = 1; 38013852Ssam break; 38113852Ssam case 'm': 38213852Ssam flags |= NOTRIMENDCOL; 38313852Ssam break; 38413852Ssam case 'g': /* gutter space */ 38513852Ssam p = getnum(&gutter, p, 0); 38613852Ssam break; 38713852Ssam case 'G': 38813852Ssam p = getnum(&propgutter, p, 0); 38913852Ssam break; 39013852Ssam case 'e': /* each line is an entry */ 39113852Ssam flags |= ONEPERLINE; 39213852Ssam break; 39313852Ssam case 'E': 39413852Ssam flags |= ONEPERCHAR; 39513852Ssam break; 39613852Ssam case 'j': /* right adjust */ 39713852Ssam flags |= RIGHTADJUST; 39813852Ssam break; 39913852Ssam case 'n': /* null padding for missing values */ 40013852Ssam flags |= NULLPAD; 40113852Ssam break; 40213852Ssam case 'y': 40313852Ssam flags |= RECYCLE; 40413852Ssam break; 40513852Ssam case 'H': /* print shape only */ 40613852Ssam flags |= DETAILSHAPE; 40713852Ssam case 'h': 40813852Ssam flags |= SHAPEONLY; 40913852Ssam break; 41013852Ssam case 'z': /* squeeze col width */ 41113852Ssam flags |= SQUEEZE; 41213852Ssam break; 41313852Ssam /*case 'p': 41413852Ssam ipagespace = atoi(++p); (default is 1) 41513852Ssam break;*/ 41613852Ssam case 'o': /* col order */ 41713852Ssam p = getlist(&cord, p); 41813852Ssam break; 41913852Ssam case 'b': 42013852Ssam flags |= ICOLBOUNDS; 42113852Ssam p = getlist(&icbd, p); 42213852Ssam break; 42313852Ssam case 'B': 42413852Ssam flags |= OCOLBOUNDS; 42513852Ssam p = getlist(&ocbd, p); 42613852Ssam break; 42713852Ssam default: 42813852Ssam error("Bad flag: %.1s", p); 42913852Ssam } 43013852Ssam /*if (!osep) 43113852Ssam osep = isep;*/ 43213852Ssam switch (ac) { 43313852Ssam /*case 3: 43413852Ssam opages = atoi(av[2]);*/ 43513852Ssam case 2: 43613852Ssam ocols = atoi(av[1]); 43713852Ssam case 1: 43813852Ssam orows = atoi(av[0]); 43913852Ssam case 0: 44013852Ssam break; 44113852Ssam default: 44213852Ssam error("Too many arguments. What do you mean by `%s'?", av[3]); 44313852Ssam } 44413852Ssam } 44513852Ssam 44613852Ssam char * 44713852Ssam getlist(list, p) 44813852Ssam short **list; 44913852Ssam char *p; 45013852Ssam { 45113852Ssam register char *t; 45213852Ssam register int count = 1; 45313852Ssam 45413852Ssam for (t = p + 1; *t; t++) { 45513852Ssam if (!isdigit(*t)) 45613852Ssam error("Option %.1s requires a list of unsigned numbers separated by commas", t); 45713852Ssam count++; 45813852Ssam while (*t && isdigit(*t)) 45913852Ssam t++; 46013852Ssam if (*t != ',') 46113852Ssam break; 46213852Ssam } 46313852Ssam if (!(*list = (short *) malloc(count * sizeof(short)))) 46413852Ssam error("No list space", ""); 46513852Ssam count = 0; 46613852Ssam for (t = p + 1; *t; t++) { 46713852Ssam (*list)[count++] = atoi(t); 46813852Ssam printf("++ %d ", (*list)[count-1]); 46913852Ssam fflush(stdout); 47013852Ssam while (*t && isdigit(*t)) 47113852Ssam t++; 47213852Ssam if (*t != ',') 47313852Ssam break; 47413852Ssam } 47513852Ssam (*list)[count] = 0; 47613852Ssam return(t - 1); 47713852Ssam } 47813852Ssam 47913852Ssam char * 48013852Ssam getnum(num, p, strict) /* num = number p points to; if (strict) complain */ 48113852Ssam int *num; /* returns pointer to end of num */ 48213852Ssam char *p; 48313852Ssam int strict; 48413852Ssam { 48513852Ssam register char *t = p; 48613852Ssam 48713852Ssam if (!isdigit(*++t)) { 48813852Ssam if (strict || *t == '-' || *t == '+') 48913852Ssam error("Option %.1s requires an unsigned integer", p); 49013852Ssam *num = 0; 49113852Ssam return(p); 49213852Ssam } 49313852Ssam *num = atoi(t); 49413852Ssam while (*++t) 49513852Ssam if (!isdigit(*t)) 49613852Ssam break; 49713852Ssam return(--t); 49813852Ssam } 499