home *** CD-ROM | disk | FTP | other *** search
/ The UNIX CD Bookshelf / OREILLY_TUCB_UNIX_CD.iso / upt / examples / SOURCES / JOT / TOOLS.Z / TOOLS / tools / rs.c < prev   
Encoding:
C/C++ Source or Header  |  1991-11-07  |  10.2 KB  |  500 lines

  1. /* Copyright (c) 1983 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char sccsid[] = "@(#)rs.c    4.3    (Berkeley)    4/5/86";
  5. #endif not lint
  6.  
  7. /*
  8.  *    rs - reshape a data array
  9.  *    Author:  John Kunze, Office of Comp. Affairs, UCB
  10.  *        BEWARE: lots of unfinished edges
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15.  
  16. long    flags;
  17. #define    TRANSPOSE    000001
  18. #define    MTRANSPOSE    000002
  19. #define    ONEPERLINE    000004
  20. #define    ONEISEPONLY    000010
  21. #define    ONEOSEPONLY    000020
  22. #define    NOTRIMENDCOL    000040
  23. #define    SQUEEZE        000100
  24. #define    SHAPEONLY    000200
  25. #define    DETAILSHAPE    000400
  26. #define    RIGHTADJUST    001000
  27. #define    NULLPAD        002000
  28. #define    RECYCLE        004000
  29. #define    SKIPPRINT    010000
  30. #define    ICOLBOUNDS    020000
  31. #define    OCOLBOUNDS    040000
  32. #define ONEPERCHAR    0100000
  33. #define NOARGS        0200000
  34.  
  35. char    buf[BUFSIZ];
  36. short    *colwidths;
  37. short    *cord;
  38. short    *icbd;
  39. short    *ocbd;
  40. int    nelem;
  41. char    **elem;
  42. char    **endelem;
  43. char    *curline;
  44. int    allocsize = BUFSIZ;
  45. int    curlen;
  46. int    irows, icols;
  47. int    orows, ocols;
  48. int    maxlen;
  49. int    skip;
  50. int    propgutter;
  51. char    isep = ' ', osep = ' ';
  52. int    owidth = 80, gutter = 2;
  53.  
  54. char    **getptrs();
  55.  
  56. main(argc, argv)
  57. int    argc;
  58. char    **argv;
  59. {
  60.     setbuf(stdout, buf);
  61.     getargs(argc, argv);
  62.     getfile();
  63.     if (flags & SHAPEONLY) {
  64.         printf("%d %d\n", irows, icols);
  65.         exit(0);
  66.     }
  67.     prepfile();
  68.     /*fprintf(stderr, "#irows %d icols %d orows %d ocols %d\n",irows,icols,orows,ocols);*/
  69.     putfile();
  70.     exit(0);
  71. }
  72.  
  73. getfile()
  74. {
  75.     register char    *p;
  76.     register char    *endp;
  77.     register char    **ep = 0;
  78.     int    multisep = (flags & ONEISEPONLY ? 0 : 1);
  79.     int    nullpad = flags & NULLPAD;
  80.     char    **padto;
  81.  
  82.     while (skip--) {
  83.         getline();
  84.         if (flags & SKIPPRINT)
  85.             puts(curline);
  86.     }
  87.     getline();
  88.     if (flags & NOARGS && curlen < owidth)
  89.         flags |= ONEPERLINE;
  90.     if (flags & ONEPERLINE)
  91.         icols = 1;
  92.     else                /* count cols on first line */
  93.         for (p = curline, endp = curline + curlen; p < endp; p++) {
  94.             if (*p == isep && multisep)
  95.                 continue;
  96.             icols++;
  97.             while (*p && *p != isep)
  98.                 p++;
  99.         }
  100.     ep = getptrs(elem);
  101.     p = curline;
  102.     do {
  103.         if (flags & ONEPERLINE) {
  104.             *ep++ = curline;
  105.             if (maxlen < curlen)
  106.                 maxlen = curlen;
  107.             irows++;
  108.             continue;
  109.         }
  110.         for (p = curline, endp = curline + curlen; p < endp; p++) {
  111.             if (*p == isep && multisep)
  112.                 continue;    /* eat up column separators */
  113.             if (*p == isep)        /* must be an empty column */
  114.                 *ep = "";
  115.             else            /* store column entry */
  116.                 *ep = p;
  117.             while (p < endp && *p != isep)
  118.                 p++;        /* find end of entry */
  119.             *p = '\0';        /* mark end of entry */
  120.             if (maxlen < p - *ep)    /* update maxlen */
  121.                 maxlen = p - *ep;
  122.             ep++;            /* prepare for next entry */
  123.         }
  124.         irows++;            /* update row count */
  125.         if (nullpad) {            /* pad missing entries */
  126.             padto = elem + irows * icols;
  127.             while  (ep < padto)
  128.                 *ep++ = "";
  129.         }
  130.     if (ep > endelem)            /* if low on pointers */
  131.         ep = getptrs(ep);        /* get some more */
  132.     } while (getline() != EOF);
  133.     *ep = 0;                /* mark end of pointers */
  134.     nelem = ep - elem;
  135. }
  136.  
  137. putfile()
  138. {
  139.     register char    **ep;
  140.     register int    i;
  141.     register int    j;
  142.  
  143.     ep = elem;
  144.     if (flags & TRANSPOSE)
  145.         for (i = 0; i < orows; i++) {
  146.             for (j = i; j < nelem; j += orows)
  147.                 prints(ep[j], (j - i) / orows);
  148.             putchar('\n');
  149.         }
  150.     else
  151.         for (i = 0; i < orows; i++) {
  152.             for (j = 0; j < ocols; j++)
  153.                 prints(*ep++, j);
  154.             putchar('\n');
  155.         }
  156. }
  157.  
  158. prints(s, col)
  159. char    *s;
  160. int    col;
  161. {
  162.     register char    *p = s;
  163.     register int    n;
  164.  
  165.     while (*p)
  166.         p++;
  167.     n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
  168.     if (flags & RIGHTADJUST)
  169.         while (n-- > 0)
  170.             putchar(osep);
  171.     for (p = s; *p; p++)
  172.         putchar(*p);
  173.     while (n-- > 0)
  174.         putchar(osep);
  175. }
  176.  
  177. error(msg, s)
  178. char    *msg;
  179. char    *s;
  180. {
  181.     fprintf(stderr, "rs:  ");
  182.     fprintf(stderr, msg, s);
  183.     fprintf(stderr, "\nUsage:  rs [ -[csCS][x][kKgGw][N]tTeEnyjhHm ] [ rows [ cols ] ]\n");
  184.     exit(1);
  185. }
  186.  
  187. prepfile()
  188. {
  189.     register char    **ep;
  190.     register int     i;
  191.     register int     j;
  192.     char    **lp;
  193.     int    colw;
  194.     int    max = 0;
  195.     int    n;
  196.  
  197.     if (!nelem)
  198.         exit(0);
  199.     gutter += maxlen * propgutter / 100.0;
  200.     colw = maxlen + gutter;
  201.     if (flags & MTRANSPOSE) {
  202.         orows = icols;
  203.         ocols = irows;
  204.     }
  205.     else if (orows == 0 && ocols == 0) {    /* decide rows and cols */
  206.         ocols = owidth / colw;
  207.         if (ocols == 0)
  208.             fprintf(stderr, "Display width %d is less than column width %d\n", owidth, colw);
  209.         if (ocols > nelem)
  210.             ocols = nelem;
  211.         orows = nelem / ocols + (nelem % ocols ? 1 : 0);
  212.     }
  213.     else if (orows == 0)            /* decide on rows */
  214.         orows = nelem / ocols + (nelem % ocols ? 1 : 0);
  215.     else if (ocols == 0)            /* decide on cols */
  216.         ocols = nelem / orows + (nelem % orows ? 1 : 0);
  217.     lp = elem + orows * ocols;
  218.     while (lp > endelem) {
  219.         getptrs(elem + nelem);
  220.         lp = elem + orows * ocols;
  221.     }
  222.     if (flags & RECYCLE) {
  223.         for (ep = elem + nelem; ep < lp; ep++)
  224.             *ep = *(ep - nelem);
  225.         nelem = lp - elem;
  226.     }
  227.     if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
  228.         error("malloc:  No gutter space", "");
  229.     if (flags & SQUEEZE) {
  230.         if (flags & TRANSPOSE)
  231.             for (ep = elem, i = 0; i < ocols; i++) {
  232.                 for (j = 0; j < orows; j++)
  233.                     if ((n = strlen(*ep++)) > max)
  234.                         max = n;
  235.                 colwidths[i] = max + gutter;
  236.             }
  237.         else
  238.             for (i = 0; i < ocols; i++) {
  239.                 for (j = i; j < nelem; j += ocols)
  240.                     if ((n = strlen(ep[j])) > max)
  241.                         max = n;
  242.                 colwidths[i] = max + gutter;
  243.             }
  244.     }
  245.     /*    for (i = 0; i < orows; i++) {
  246.             for (j = i; j < nelem; j += orows)
  247.                 prints(ep[j], (j - i) / orows);
  248.             putchar('\n');
  249.         }
  250.     else
  251.         for (i = 0; i < orows; i++) {
  252.             for (j = 0; j < ocols; j++)
  253.                 prints(*ep++, j);
  254.             putchar('\n');
  255.         }*/
  256.     else
  257.         for (i = 0; i < ocols; i++)
  258.             colwidths[i] = colw;
  259.     if (!(flags & NOTRIMENDCOL)) {
  260.         if (flags & RIGHTADJUST)
  261.             colwidths[0] -= gutter;
  262.         else
  263.             colwidths[ocols - 1] = 0;
  264.     }
  265.     n = orows * ocols;
  266.     if (n > nelem && (flags & RECYCLE))
  267.         nelem = n;
  268.     /*for (i = 0; i < ocols; i++)
  269.         fprintf(stderr, "%d ",colwidths[i]);
  270.     fprintf(stderr, "is colwidths, nelem %d\n", nelem);*/
  271. }
  272.  
  273. #define    BSIZE    2048
  274. char    ibuf[BSIZE];        /* two screenfuls should do */
  275.  
  276. getline()    /* get line; maintain curline, curlen; manage storage */
  277. {
  278.     register char    *p;
  279.     register int    c;
  280.     register int    i;
  281.     static    int    putlength;
  282.     static    char    *endblock = ibuf + BSIZE;
  283.  
  284.     if (!irows) {
  285.         curline = ibuf;
  286.         putlength = flags & DETAILSHAPE;
  287.     }
  288.     else if (skip <= 0) {            /* don't waste storage */
  289.         curline += curlen + 1;
  290.         if (putlength)        /* print length, recycle storage */
  291.             printf(" %d line %d\n", curlen, irows);
  292.     }
  293.     if (!putlength && endblock - curline < BUFSIZ) {   /* need storage */
  294.         /*ww = endblock-curline; tt += ww;*/
  295.         /*printf("#wasted %d total %d\n",ww,tt);*/
  296.         if (!(curline = (char *) malloc(BSIZE)))
  297.             error("File too large", "");
  298.         endblock = curline + BSIZE;
  299.         /*printf("#endb %d curline %d\n",endblock,curline);*/
  300.     }
  301.     for (p = curline, i = 1; i < BUFSIZ; *p++ = c, i++)
  302.         if ((c = getchar()) == EOF || c == '\n')
  303.             break;
  304.     *p = '\0';
  305.     curlen = i - 1;
  306.     return(c);
  307. }
  308.  
  309. char    **
  310. getptrs(sp)
  311. char    **sp;
  312. {
  313.     register char    **p;
  314.     register char    **ep;
  315.  
  316.     for (;;) {
  317.         allocsize += allocsize;
  318.         if (!(p = (char **) malloc(allocsize * sizeof(char *)))) {
  319.             perror("rs");
  320.             exit(1);
  321.         }
  322.         if ((endelem = p + allocsize - icols) <= p) {
  323.             free(p);
  324.             continue;
  325.         }
  326.         if (elem != 0)
  327.             free(elem);
  328.         ep = elem;
  329.         elem = p;
  330.         while (ep < sp)
  331.             *p++ = *ep++;
  332.         return(p);
  333.     }
  334. }
  335.  
  336. getargs(ac, av)
  337. int    ac;
  338. char    **av;
  339. {
  340.     register char    *p;
  341.     char    *getnum(), *getlist();
  342.  
  343.     if (ac == 1) {
  344.         flags |= NOARGS | TRANSPOSE;
  345.     }
  346.     while (--ac && **++av == '-')
  347.         for (p = *av+1; *p; p++)
  348.             switch (*p) {
  349.             case 'T':
  350.                 flags |= MTRANSPOSE;
  351.             case 't':
  352.                 flags |= TRANSPOSE;
  353.                 break;
  354.             case 'c':        /* input col. separator */
  355.                 flags |= ONEISEPONLY;
  356.             case 's':        /* one or more allowed */
  357.                 if (p[1])
  358.                     isep = *++p;
  359.                 else
  360.                     isep = '\t';    /* default is ^I */
  361.                 break;
  362.             case 'C':
  363.                 flags |= ONEOSEPONLY;
  364.             case 'S':
  365.                 if (p[1])
  366.                     osep = *++p;
  367.                 else
  368.                     osep = '\t';    /* default is ^I */
  369.                 break;
  370.             case 'w':        /* window width, default 80 */
  371.                 p = getnum(&owidth, p, 0);
  372.                 if (owidth <= 0)
  373.                     error("Width must be a positive integer", "");
  374.                 break;
  375.             case 'K':            /* skip N lines */
  376.                 flags |= SKIPPRINT;
  377.             case 'k':            /* skip, do not print */
  378.                 p = getnum(&skip, p, 0);
  379.                 if (!skip)
  380.                     skip = 1;
  381.                 break;
  382.             case 'm':
  383.                 flags |= NOTRIMENDCOL;
  384.                 break;
  385.             case 'g':        /* gutter space */
  386.                 p = getnum(&gutter, p, 0);
  387.                 break;
  388.             case 'G':
  389.                 p = getnum(&propgutter, p, 0);
  390.                 break;
  391.             case 'e':        /* each line is an entry */
  392.                 flags |= ONEPERLINE;
  393.                 break;
  394.             case 'E':
  395.                 flags |= ONEPERCHAR;
  396.                 break;
  397.             case 'j':            /* right adjust */
  398.                 flags |= RIGHTADJUST;
  399.                 break;
  400.             case 'n':    /* null padding for missing values */
  401.                 flags |= NULLPAD;
  402.                 break;
  403.             case 'y':
  404.                 flags |= RECYCLE;
  405.                 break;
  406.             case 'H':            /* print shape only */
  407.                 flags |= DETAILSHAPE;
  408.             case 'h':
  409.                 flags |= SHAPEONLY;
  410.                 break;
  411.             case 'z':            /* squeeze col width */
  412.                 flags |= SQUEEZE;
  413.                 break;
  414.             /*case 'p':
  415.                 ipagespace = atoi(++p);    (default is 1)
  416.                 break;*/
  417.             case 'o':            /* col order */
  418.                 p = getlist(&cord, p);
  419.                 break;
  420.             case 'b':
  421.                 flags |= ICOLBOUNDS;
  422.                 p = getlist(&icbd, p);
  423.                 break;
  424.             case 'B':
  425.                 flags |= OCOLBOUNDS;
  426.                 p = getlist(&ocbd, p);
  427.                 break;
  428.             default:
  429.                 error("Bad flag:  %.1s", p);
  430.             }
  431.     /*if (!osep)
  432.         osep = isep;*/
  433.     switch (ac) {
  434.     /*case 3:
  435.         opages = atoi(av[2]);*/
  436.     case 2:
  437.         ocols = atoi(av[1]);
  438.     case 1:
  439.         orows = atoi(av[0]);
  440.     case 0:
  441.         break;
  442.     default:
  443.         error("Too many arguments.  What do you mean by `%s'?", av[3]);
  444.     }
  445. }
  446.  
  447. char    *
  448. getlist(list, p)
  449. short    **list;
  450. char    *p;
  451. {
  452.     register char    *t;
  453.     register int    count = 1;
  454.  
  455.     for (t = p + 1; *t; t++) {
  456.         if (!isdigit(*t))
  457.             error("Option %.1s requires a list of unsigned numbers separated by commas", t);
  458.         count++;
  459.         while (*t && isdigit(*t))
  460.             t++;
  461.         if (*t != ',')
  462.             break;
  463.     }
  464.     if (!(*list = (short *) malloc(count * sizeof(short))))
  465.         error("No list space", "");
  466.     count = 0;
  467.     for (t = p + 1; *t; t++) {
  468.         (*list)[count++] = atoi(t);
  469.         printf("++ %d ", (*list)[count-1]);
  470.         fflush(stdout);
  471.         while (*t && isdigit(*t))
  472.             t++;
  473.         if (*t != ',')
  474.             break;
  475.     }
  476.     (*list)[count] = 0;
  477.     return(t - 1);
  478. }
  479.  
  480. char    *
  481. getnum(num, p, strict)    /* num = number p points to; if (strict) complain */
  482. int    *num;                /* returns pointer to end of num */
  483. char    *p;
  484. int    strict;
  485. {
  486.     register char    *t = p;
  487.  
  488.     if (!isdigit(*++t)) {
  489.         if (strict || *t == '-' || *t == '+')
  490.             error("Option %.1s requires an unsigned integer", p);
  491.         *num = 0;
  492.         return(p);
  493.     }
  494.     *num = atoi(t);
  495.     while (*++t)
  496.         if (!isdigit(*t))
  497.             break;
  498.     return(--t);
  499. }
  500.