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