date and time created 83/07/08 02:24:46 by sam
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Fri, 8 Jul 1983 17:24:46 +0000 (09:24 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Fri, 8 Jul 1983 17:24:46 +0000 (09:24 -0800)
SCCS-vsn: usr.bin/rs/rs.c 4.1

usr/src/usr.bin/rs/rs.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/rs/rs.c b/usr/src/usr.bin/rs/rs.c
new file mode 100644 (file)
index 0000000..36f637a
--- /dev/null
@@ -0,0 +1,493 @@
+/* Copyright (c) 1983 Regents of the University of California */
+
+#ifndef lint
+static char sccsid[] = "@(#)rs.c       4.1     (Berkeley)      %G%";
+#endif not lint
+
+/*
+ *     rs - reshape a data array
+ *     Author:  John Kunze, Office of Comp. Affairs, UCB
+ *             BEWARE: lots of unfinished edges
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+long   flags;
+#define        TRANSPOSE       000001
+#define        MTRANSPOSE      000002
+#define        ONEPERLINE      000004
+#define        ONEISEPONLY     000010
+#define        ONEOSEPONLY     000020
+#define        NOTRIMENDCOL    000040
+#define        SQUEEZE         000100
+#define        SHAPEONLY       000200
+#define        DETAILSHAPE     000400
+#define        RIGHTADJUST     001000
+#define        NULLPAD         002000
+#define        RECYCLE         004000
+#define        SKIPPRINT       010000
+#define        ICOLBOUNDS      020000
+#define        OCOLBOUNDS      040000
+#define ONEPERCHAR     0100000
+
+char   buf[BUFSIZ];
+short  *colwidths;
+short  *cord;
+short  *icbd;
+short  *ocbd;
+int    nelem;
+char   **elem;
+char   **endelem;
+char   *curline;
+int    allocsize = BUFSIZ;
+int    curlen;
+int    irows, icols;
+int    orows, ocols;
+int    maxlen;
+int    skip;
+int    propgutter;
+char   isep = ' ', osep = ' ';
+int    owidth = 80, gutter = 2;
+
+char   **getptrs();
+
+main(argc, argv)
+int    argc;
+char   **argv;
+{
+       setbuf(stdout, buf);
+       getargs(argc, argv);
+       getfile();
+       if (flags & SHAPEONLY) {
+               printf("%d %d\n", irows, icols);
+               exit(0);
+       }
+       prepfile();
+       /*fprintf(stderr, "#irows %d icols %d orows %d ocols %d\n",irows,icols,orows,ocols);*/
+       putfile();
+}
+
+getfile()
+{
+       register char   *p;
+       register char   *endp;
+       register char   **ep = 0;
+       int     multisep = (flags & ONEISEPONLY ? 0 : 1);
+       int     nullpad = flags & NULLPAD;
+       char    **padto;
+
+       while (skip--) {
+               getline();
+               if (flags & SKIPPRINT)
+                       puts(curline);
+       }
+       getline();
+       if (flags & ONEPERLINE)
+               icols = 1;
+       else                            /* count cols on first line */
+               for (p = curline, endp = curline + curlen; p < endp; p++) {
+                       if (*p == isep && multisep)
+                               continue;
+                       icols++;
+                       while (*p && *p != isep)
+                               p++;
+               }
+       ep = getptrs(elem);
+       p = curline;
+       do {
+               if (flags & ONEPERLINE) {
+                       *ep++ = curline;
+                       if (maxlen < curlen)
+                               maxlen = curlen;
+                       irows++;
+                       continue;
+               }
+               for (p = curline, endp = curline + curlen; p < endp; p++) {
+                       if (*p == isep && multisep)
+                               continue;       /* eat up column separators */
+                       if (*p == isep)         /* must be an empty column */
+                               *ep = "";
+                       else                    /* store column entry */
+                               *ep = p;
+                       while (p < endp && *p != isep)
+                               p++;            /* find end of entry */
+                       *p = '\0';              /* mark end of entry */
+                       if (maxlen < p - *ep)   /* update maxlen */
+                               maxlen = p - *ep;
+                       ep++;                   /* prepare for next entry */
+               }
+               irows++;                        /* update row count */
+               if (nullpad) {                  /* pad missing entries */
+                       padto = elem + irows * icols;
+                       while  (ep < padto)
+                               *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;
+}
+
+putfile()
+{
+       register char   **ep;
+       register int    i;
+       register int    j;
+
+       ep = elem;
+       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++)
+                               prints(*ep++, j);
+                       putchar('\n');
+               }
+}
+
+prints(s, col)
+char   *s;
+int    col;
+{
+       register char   *p = s;
+       register int    n;
+
+       while (*p)
+               p++;
+       n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
+       if (flags & RIGHTADJUST)
+               while (n-- > 0)
+                       putchar(osep);
+       for (p = s; *p; p++)
+               putchar(*p);
+       while (n-- > 0)
+               putchar(osep);
+}
+
+error(msg, s)
+char   *msg;
+char   *s;
+{
+       fprintf(stderr, "rs:  ");
+       fprintf(stderr, msg, s);
+       fprintf(stderr, "\nUsage:  rs [ -[csCS][x][kKgGw][N]tTeEnyjhHm ] [ rows [ cols ] ]\n");
+       exit(1);
+}
+
+prepfile()
+{
+       register char   **ep;
+       register int    i;
+       register int    j;
+       char    **lp;
+       int     colw;
+       int     max = 0;
+       int     n;
+
+       if (!nelem)
+               exit(0);
+       gutter += maxlen * propgutter / 100.0;
+       colw = maxlen + gutter;
+       if (flags & MTRANSPOSE) {
+               orows = icols;
+               ocols = irows;
+       }
+       else if (orows == 0 && ocols == 0) {    /* decide rows and cols */
+               ocols = owidth / colw;          /* not a good idea */
+               if (ocols > nelem)
+                       ocols = nelem;
+               orows = nelem / ocols + (nelem % ocols ? 1 : 0);
+       }
+       else if (orows == 0)                    /* decide on rows */
+               orows = nelem / ocols + (nelem % ocols ? 1 : 0);
+       else if (ocols == 0)                    /* decide on cols */
+               ocols = nelem / orows + (nelem % orows ? 1 : 0);
+       lp = elem + orows * ocols;
+       while (lp > endelem) {
+               getptrs(elem + nelem);
+               lp = elem + orows * ocols;
+       }
+       if (flags & RECYCLE) {
+               for (ep = elem + nelem; ep < lp; ep++)
+                       *ep = *(ep - nelem);
+               nelem = lp - elem;
+       }
+       if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
+               error("malloc:  No gutter space", "");
+       if (flags & SQUEEZE) {
+               if (flags & TRANSPOSE)
+                       for (ep = elem, i = 0; i < ocols; i++) {
+                               for (j = 0; j < orows; j++)
+                                       if ((n = strlen(*ep++)) > max)
+                                               max = n;
+                               colwidths[i] = max + gutter;
+                       }
+               else
+                       for (i = 0; i < ocols; i++) {
+                               for (j = i; j < nelem; j += ocols)
+                                       if ((n = strlen(ep[j])) > max)
+                                               max = n;
+                               colwidths[i] = max + gutter;
+                       }
+       }
+       /*      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++)
+                               prints(*ep++, j);
+                       putchar('\n');
+               }*/
+       else
+               for (i = 0; i < ocols; i++)
+                       colwidths[i] = colw;
+       if (!(flags & NOTRIMENDCOL)) {
+               if (flags & RIGHTADJUST)
+                       colwidths[0] -= gutter;
+               else
+                       colwidths[ocols - 1] = 0;
+       }
+       n = orows * ocols;
+       if (n > nelem && (flags & RECYCLE))
+               nelem = n;
+       /*for (i = 0; i < ocols; i++)
+               fprintf(stderr, "%d ",colwidths[i]);
+       fprintf(stderr, "is colwidths, nelem %d\n", nelem);*/
+}
+
+#define        BSIZE   2048
+char   ibuf[BSIZE];            /* two screenfuls should do */
+
+getline()      /* get line; maintain curline, curlen; manage storage */
+{
+       register char   *p;
+       register int    c;
+       register int    i;
+       static  int     putlength;
+       static  char    *endblock = ibuf + BSIZE;
+
+       if (!irows) {
+               curline = ibuf;
+               putlength = flags & DETAILSHAPE;
+       }
+       else if (skip <= 0) {                   /* don't waste storage */
+               curline += curlen + 1;
+               if (putlength)          /* print length, recycle storage */
+                       printf(" %d line %d\n", curlen, irows);
+       }
+       if (!putlength && endblock - curline < BUFSIZ) {   /* need storage */
+               /*ww = endblock-curline; tt += ww;*/
+               /*printf("#wasted %d total %d\n",ww,tt);*/
+               if (!(curline = (char *) malloc(BSIZE)))
+                       error("File too large", "");
+               endblock = curline + BSIZE;
+               /*printf("#endb %d curline %d\n",endblock,curline);*/
+       }
+       for (p = curline, i = 1; i < BUFSIZ; *p++ = c, i++)
+               if ((c = getchar()) == EOF || c == '\n')
+                       break;
+       *p = '\0';
+       curlen = i - 1;
+       return(c);
+}
+
+char   **
+getptrs(sp)
+char   **sp;
+{
+       register char   **p;
+       register char   **ep;
+
+       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);
+       }
+}
+
+getargs(ac, av)
+int    ac;
+char   **av;
+{
+       register char   *p;
+       char    *getnum(), *getlist();
+
+       if (ac == 1) {
+               flags |= ONEPERLINE | TRANSPOSE;
+       }
+       while (--ac && **++av == '-')
+               for (p = *av+1; *p; p++)
+                       switch (*p) {
+                       case 'T':
+                               flags |= MTRANSPOSE;
+                       case 't':
+                               flags |= TRANSPOSE;
+                               break;
+                       case 'c':               /* input col. separator */
+                               flags |= ONEISEPONLY;
+                       case 's':               /* one or more allowed */
+                               if (p[1])
+                                       isep = *++p;
+                               else
+                                       isep = '\t';    /* default is ^I */
+                               break;
+                       case 'C':
+                               flags |= ONEOSEPONLY;
+                       case 'S':
+                               if (p[1])
+                                       osep = *++p;
+                               else
+                                       osep = '\t';    /* default is ^I */
+                               break;
+                       case 'w':               /* window width, default 80 */
+                               p = getnum(&owidth, p, 0);
+                               if (owidth <= 0)
+                                       error("Width must be a positive integer", "");
+                               break;
+                       case 'K':                       /* skip N lines */
+                               flags |= SKIPPRINT;
+                       case 'k':                       /* skip, do not print */
+                               p = getnum(&skip, p, 0);
+                               if (!skip)
+                                       skip = 1;
+                               break;
+                       case 'm':
+                               flags |= NOTRIMENDCOL;
+                               break;
+                       case 'g':               /* gutter space */
+                               p = getnum(&gutter, p, 0);
+                               break;
+                       case 'G':
+                               p = getnum(&propgutter, p, 0);
+                               break;
+                       case 'e':               /* each line is an entry */
+                               flags |= ONEPERLINE;
+                               break;
+                       case 'E':
+                               flags |= ONEPERCHAR;
+                               break;
+                       case 'j':                       /* right adjust */
+                               flags |= RIGHTADJUST;
+                               break;
+                       case 'n':       /* null padding for missing values */
+                               flags |= NULLPAD;
+                               break;
+                       case 'y':
+                               flags |= RECYCLE;
+                               break;
+                       case 'H':                       /* print shape only */
+                               flags |= DETAILSHAPE;
+                       case 'h':
+                               flags |= SHAPEONLY;
+                               break;
+                       case 'z':                       /* squeeze col width */
+                               flags |= SQUEEZE;
+                               break;
+                       /*case 'p':
+                               ipagespace = atoi(++p); (default is 1)
+                               break;*/
+                       case 'o':                       /* col order */
+                               p = getlist(&cord, p);
+                               break;
+                       case 'b':
+                               flags |= ICOLBOUNDS;
+                               p = getlist(&icbd, p);
+                               break;
+                       case 'B':
+                               flags |= OCOLBOUNDS;
+                               p = getlist(&ocbd, p);
+                               break;
+                       default:
+                               error("Bad flag:  %.1s", p);
+                       }
+       /*if (!osep)
+               osep = isep;*/
+       switch (ac) {
+       /*case 3:
+               opages = atoi(av[2]);*/
+       case 2:
+               ocols = atoi(av[1]);
+       case 1:
+               orows = atoi(av[0]);
+       case 0:
+               break;
+       default:
+               error("Too many arguments.  What do you mean by `%s'?", av[3]);
+       }
+}
+
+char   *
+getlist(list, p)
+short  **list;
+char   *p;
+{
+       register char   *t;
+       register int    count = 1;
+
+       for (t = p + 1; *t; t++) {
+               if (!isdigit(*t))
+                       error("Option %.1s requires a list of unsigned numbers separated by commas", t);
+               count++;
+               while (*t && isdigit(*t))
+                       t++;
+               if (*t != ',')
+                       break;
+       }
+       if (!(*list = (short *) malloc(count * sizeof(short))))
+               error("No list space", "");
+       count = 0;
+       for (t = p + 1; *t; t++) {
+               (*list)[count++] = atoi(t);
+               printf("++ %d ", (*list)[count-1]);
+               fflush(stdout);
+               while (*t && isdigit(*t))
+                       t++;
+               if (*t != ',')
+                       break;
+       }
+       (*list)[count] = 0;
+       return(t - 1);
+}
+
+char   *
+getnum(num, p, strict) /* num = number p points to; if (strict) complain */
+int    *num;                           /* returns pointer to end of num */
+char   *p;
+int    strict;
+{
+       register char   *t = p;
+
+       if (!isdigit(*++t)) {
+               if (strict || *t == '-' || *t == '+')
+                       error("Option %.1s requires an unsigned integer", p);
+               *num = 0;
+               return(p);
+       }
+       *num = atoi(t);
+       while (*++t)
+               if (!isdigit(*t))
+                       break;
+       return(--t);
+}