[BACK]Return to rs.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rs

Annotation of src/usr.bin/rs/rs.c, Revision 1.11

1.11    ! tedu        1: /*     $OpenBSD: rs.c,v 1.10 2003/10/16 16:57:14 tedu Exp $    */
1.3       deraadt     2:
1.1       deraadt     3: /*-
                      4:  * Copyright (c) 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
1.8       millert    15:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
                     32: #ifndef lint
                     33: static char copyright[] =
                     34: "@(#) Copyright (c) 1993\n\
                     35:        The Regents of the University of California.  All rights reserved.\n";
                     36: #endif /* not lint */
                     37:
                     38: #ifndef lint
                     39: static char sccsid[] = "@(#)rs.c       8.1 (Berkeley) 6/6/93";
                     40: #endif /* not lint */
                     41:
                     42: /*
                     43:  *     rs - reshape a data array
                     44:  *     Author:  John Kunze, Office of Comp. Affairs, UCB
                     45:  *             BEWARE: lots of unfinished edges
                     46:  */
                     47:
                     48: #include <ctype.h>
1.4       millert    49: #include <err.h>
1.1       deraadt    50: #include <stdio.h>
                     51: #include <stdlib.h>
                     52: #include <string.h>
                     53:
                     54: long   flags;
                     55: #define        TRANSPOSE       000001
                     56: #define        MTRANSPOSE      000002
                     57: #define        ONEPERLINE      000004
                     58: #define        ONEISEPONLY     000010
                     59: #define        ONEOSEPONLY     000020
                     60: #define        NOTRIMENDCOL    000040
                     61: #define        SQUEEZE         000100
                     62: #define        SHAPEONLY       000200
                     63: #define        DETAILSHAPE     000400
                     64: #define        RIGHTADJUST     001000
                     65: #define        NULLPAD         002000
                     66: #define        RECYCLE         004000
                     67: #define        SKIPPRINT       010000
                     68: #define        ICOLBOUNDS      020000
                     69: #define        OCOLBOUNDS      040000
                     70: #define ONEPERCHAR     0100000
                     71: #define NOARGS         0200000
                     72:
                     73: short  *colwidths;
                     74: short  *cord;
                     75: short  *icbd;
                     76: short  *ocbd;
                     77: int    nelem;
                     78: char   **elem;
                     79: char   **endelem;
                     80: char   *curline;
                     81: int    allocsize = BUFSIZ;
                     82: int    curlen;
                     83: int    irows, icols;
                     84: int    orows, ocols;
                     85: int    maxlen;
                     86: int    skip;
                     87: int    propgutter;
                     88: char   isep = ' ', osep = ' ';
                     89: int    owidth = 80, gutter = 2;
                     90:
1.7       millert    91: void     usage(char *, char *);
                     92: void     getargs(int, char *[]);
                     93: void     getfile(void);
                     94: int      getline(void);
                     95: char    *getlist(short **, char *);
                     96: char    *getnum(int *, char *, int);
                     97: char   **getptrs(char **);
                     98: void     prepfile(void);
                     99: void     prints(char *, int);
                    100: void     putfile(void);
1.1       deraadt   101:
1.2       deraadt   102: #define INCR(ep) do {                  \
                    103:        if (++ep >= endelem)            \
                    104:                ep = getptrs(ep);       \
                    105: } while(0)
                    106:
1.1       deraadt   107: int
1.9       deraadt   108: main(int argc, char *argv[])
1.1       deraadt   109: {
                    110:        getargs(argc, argv);
                    111:        getfile();
                    112:        if (flags & SHAPEONLY) {
                    113:                printf("%d %d\n", irows, icols);
                    114:                exit(0);
                    115:        }
                    116:        prepfile();
                    117:        putfile();
                    118:        exit(0);
                    119: }
                    120:
                    121: void
1.9       deraadt   122: getfile(void)
1.1       deraadt   123: {
1.6       mpech     124:        char *p;
                    125:        char *endp;
1.11    ! tedu      126:        char **ep = NULL;
1.1       deraadt   127:        int multisep = (flags & ONEISEPONLY ? 0 : 1);
                    128:        int nullpad = flags & NULLPAD;
                    129:        char **padto;
                    130:
                    131:        while (skip--) {
                    132:                getline();
                    133:                if (flags & SKIPPRINT)
                    134:                        puts(curline);
                    135:        }
                    136:        getline();
                    137:        if (flags & NOARGS && curlen < owidth)
                    138:                flags |= ONEPERLINE;
                    139:        if (flags & ONEPERLINE)
                    140:                icols = 1;
                    141:        else                            /* count cols on first line */
                    142:                for (p = curline, endp = curline + curlen; p < endp; p++) {
                    143:                        if (*p == isep && multisep)
                    144:                                continue;
                    145:                        icols++;
                    146:                        while (*p && *p != isep)
                    147:                                p++;
                    148:                }
                    149:        ep = getptrs(elem);
                    150:        p = curline;
                    151:        do {
                    152:                if (flags & ONEPERLINE) {
1.2       deraadt   153:                        *ep = curline;
                    154:                        INCR(ep);               /* prepare for next entry */
1.1       deraadt   155:                        if (maxlen < curlen)
                    156:                                maxlen = curlen;
                    157:                        irows++;
                    158:                        continue;
                    159:                }
                    160:                for (p = curline, endp = curline + curlen; p < endp; p++) {
                    161:                        if (*p == isep && multisep)
                    162:                                continue;       /* eat up column separators */
                    163:                        if (*p == isep)         /* must be an empty column */
                    164:                                *ep = "";
                    165:                        else                    /* store column entry */
                    166:                                *ep = p;
                    167:                        while (p < endp && *p != isep)
                    168:                                p++;            /* find end of entry */
                    169:                        *p = '\0';              /* mark end of entry */
                    170:                        if (maxlen < p - *ep)   /* update maxlen */
                    171:                                maxlen = p - *ep;
1.2       deraadt   172:                        INCR(ep);               /* prepare for next entry */
1.1       deraadt   173:                }
                    174:                irows++;                        /* update row count */
                    175:                if (nullpad) {                  /* pad missing entries */
                    176:                        padto = elem + irows * icols;
1.2       deraadt   177:                        while (ep < padto) {
                    178:                                *ep = "";
                    179:                                INCR(ep);
                    180:                        }
1.1       deraadt   181:                }
                    182:        } while (getline() != EOF);
1.11    ! tedu      183:        *ep = NULL;                             /* mark end of pointers */
1.1       deraadt   184:        nelem = ep - elem;
                    185: }
                    186:
                    187: void
1.9       deraadt   188: putfile(void)
1.1       deraadt   189: {
1.6       mpech     190:        char **ep;
                    191:        int i, j, n;
1.1       deraadt   192:
                    193:        ep = elem;
1.2       deraadt   194:        if (flags & TRANSPOSE) {
1.1       deraadt   195:                for (i = 0; i < orows; i++) {
                    196:                        for (j = i; j < nelem; j += orows)
                    197:                                prints(ep[j], (j - i) / orows);
                    198:                        putchar('\n');
                    199:                }
1.2       deraadt   200:        } else {
                    201:                for (n = 0, i = 0; i < orows && n < nelem; i++) {
                    202:                        for (j = 0; j < ocols; j++) {
                    203:                                if (n++ >= nelem)
                    204:                                        break;
1.1       deraadt   205:                                prints(*ep++, j);
1.2       deraadt   206:                        }
1.1       deraadt   207:                        putchar('\n');
                    208:                }
1.2       deraadt   209:        }
1.1       deraadt   210: }
                    211:
                    212: void
1.9       deraadt   213: prints(char *s, int col)
1.1       deraadt   214: {
1.6       mpech     215:        int n;
                    216:        char *p = s;
1.1       deraadt   217:
                    218:        while (*p)
                    219:                p++;
                    220:        n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
                    221:        if (flags & RIGHTADJUST)
                    222:                while (n-- > 0)
                    223:                        putchar(osep);
                    224:        for (p = s; *p; p++)
                    225:                putchar(*p);
                    226:        while (n-- > 0)
                    227:                putchar(osep);
                    228: }
                    229:
                    230: void
1.9       deraadt   231: usage(char *msg, char *s)
1.1       deraadt   232: {
1.2       deraadt   233:        warnx(msg, s);
1.1       deraadt   234:        fprintf(stderr,
1.2       deraadt   235: "Usage:  rs [ -[csCS][x][kKgGw][N]tTeEnyjhHm ] [ rows [ cols ] ]\n");
1.1       deraadt   236:        exit(1);
                    237: }
                    238:
                    239: void
1.9       deraadt   240: prepfile(void)
1.1       deraadt   241: {
1.6       mpech     242:        char **ep;
                    243:        int  i;
                    244:        int  j;
1.1       deraadt   245:        char **lp;
                    246:        int colw;
                    247:        int max = 0;
                    248:        int n;
                    249:
                    250:        if (!nelem)
                    251:                exit(0);
                    252:        gutter += maxlen * propgutter / 100.0;
                    253:        colw = maxlen + gutter;
                    254:        if (flags & MTRANSPOSE) {
                    255:                orows = icols;
                    256:                ocols = irows;
                    257:        }
                    258:        else if (orows == 0 && ocols == 0) {    /* decide rows and cols */
                    259:                ocols = owidth / colw;
1.2       deraadt   260:                if (ocols == 0) {
1.4       millert   261:                        warnx("Display width %d is less than column width %d",
                    262:                            owidth, colw);
1.2       deraadt   263:                        ocols = 1;
                    264:                }
1.1       deraadt   265:                if (ocols > nelem)
                    266:                        ocols = nelem;
                    267:                orows = nelem / ocols + (nelem % ocols ? 1 : 0);
                    268:        }
                    269:        else if (orows == 0)                    /* decide on rows */
                    270:                orows = nelem / ocols + (nelem % ocols ? 1 : 0);
                    271:        else if (ocols == 0)                    /* decide on cols */
                    272:                ocols = nelem / orows + (nelem % orows ? 1 : 0);
                    273:        lp = elem + orows * ocols;
                    274:        while (lp > endelem) {
                    275:                getptrs(elem + nelem);
                    276:                lp = elem + orows * ocols;
                    277:        }
                    278:        if (flags & RECYCLE) {
                    279:                for (ep = elem + nelem; ep < lp; ep++)
                    280:                        *ep = *(ep - nelem);
                    281:                nelem = lp - elem;
                    282:        }
                    283:        if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
1.2       deraadt   284:                errx(1, "malloc:  No gutter space");
1.1       deraadt   285:        if (flags & SQUEEZE) {
                    286:                if (flags & TRANSPOSE)
                    287:                        for (ep = elem, i = 0; i < ocols; i++) {
                    288:                                for (j = 0; j < orows; j++)
                    289:                                        if ((n = strlen(*ep++)) > max)
                    290:                                                max = n;
                    291:                                colwidths[i] = max + gutter;
                    292:                        }
                    293:                else
1.5       deraadt   294:                        for (ep = elem, i = 0; i < ocols; i++) {
1.1       deraadt   295:                                for (j = i; j < nelem; j += ocols)
                    296:                                        if ((n = strlen(ep[j])) > max)
                    297:                                                max = n;
                    298:                                colwidths[i] = max + gutter;
                    299:                        }
                    300:        }
                    301:        /*      for (i = 0; i < orows; i++) {
                    302:                        for (j = i; j < nelem; j += orows)
                    303:                                prints(ep[j], (j - i) / orows);
                    304:                        putchar('\n');
                    305:                }
                    306:        else
                    307:                for (i = 0; i < orows; i++) {
                    308:                        for (j = 0; j < ocols; j++)
                    309:                                prints(*ep++, j);
                    310:                        putchar('\n');
                    311:                }*/
                    312:        else
                    313:                for (i = 0; i < ocols; i++)
                    314:                        colwidths[i] = colw;
                    315:        if (!(flags & NOTRIMENDCOL)) {
                    316:                if (flags & RIGHTADJUST)
                    317:                        colwidths[0] -= gutter;
                    318:                else
                    319:                        colwidths[ocols - 1] = 0;
                    320:        }
                    321:        n = orows * ocols;
                    322:        if (n > nelem && (flags & RECYCLE))
                    323:                nelem = n;
                    324:        /*for (i = 0; i < ocols; i++)
                    325:                fprintf(stderr, "%d ",colwidths[i]);
                    326:        fprintf(stderr, "is colwidths, nelem %d\n", nelem);*/
                    327: }
                    328:
                    329: #define        BSIZE   2048
                    330: char   ibuf[BSIZE];            /* two screenfuls should do */
                    331:
                    332: int
1.9       deraadt   333: getline(void)  /* get line; maintain curline, curlen; manage storage */
1.1       deraadt   334: {
                    335:        static  int putlength;
                    336:        static  char *endblock = ibuf + BSIZE;
1.6       mpech     337:        char *p;
                    338:        int c, i;
1.1       deraadt   339:
                    340:        if (!irows) {
                    341:                curline = ibuf;
                    342:                putlength = flags & DETAILSHAPE;
                    343:        }
                    344:        else if (skip <= 0) {                   /* don't waste storage */
                    345:                curline += curlen + 1;
                    346:                if (putlength)          /* print length, recycle storage */
                    347:                        printf(" %d line %d\n", curlen, irows);
                    348:        }
                    349:        if (!putlength && endblock - curline < BUFSIZ) {   /* need storage */
                    350:                /*ww = endblock-curline; tt += ww;*/
                    351:                /*printf("#wasted %d total %d\n",ww,tt);*/
                    352:                if (!(curline = (char *) malloc(BSIZE)))
1.2       deraadt   353:                        errx(1, "File too large");
1.1       deraadt   354:                endblock = curline + BSIZE;
                    355:                /*printf("#endb %d curline %d\n",endblock,curline);*/
                    356:        }
                    357:        for (p = curline, i = 1; i < BUFSIZ; *p++ = c, i++)
                    358:                if ((c = getchar()) == EOF || c == '\n')
                    359:                        break;
                    360:        *p = '\0';
                    361:        curlen = i - 1;
                    362:        return(c);
                    363: }
                    364:
                    365: char **
1.9       deraadt   366: getptrs(char **sp)
1.1       deraadt   367: {
1.6       mpech     368:        char **p;
1.10      tedu      369:        int newsize, gap;
1.1       deraadt   370:
1.10      tedu      371:        newsize = allocsize * 2;
                    372:        p = realloc(elem, newsize * sizeof(char *));
                    373:        if (p == NULL)
1.2       deraadt   374:                err(1, "no memory");
                    375:
1.10      tedu      376:        gap = p - elem;
                    377:        elem = p;
                    378:        allocsize = newsize;
                    379:        sp += gap;
                    380:        endelem = elem + allocsize;
1.2       deraadt   381:        return(sp);
1.1       deraadt   382: }
                    383:
                    384: void
1.9       deraadt   385: getargs(int ac, char *av[])
1.1       deraadt   386: {
1.6       mpech     387:        char *p;
1.1       deraadt   388:
                    389:        if (ac == 1) {
                    390:                flags |= NOARGS | TRANSPOSE;
                    391:        }
                    392:        while (--ac && **++av == '-')
                    393:                for (p = *av+1; *p; p++)
                    394:                        switch (*p) {
                    395:                        case 'T':
                    396:                                flags |= MTRANSPOSE;
                    397:                        case 't':
                    398:                                flags |= TRANSPOSE;
                    399:                                break;
                    400:                        case 'c':               /* input col. separator */
                    401:                                flags |= ONEISEPONLY;
                    402:                        case 's':               /* one or more allowed */
                    403:                                if (p[1])
                    404:                                        isep = *++p;
                    405:                                else
                    406:                                        isep = '\t';    /* default is ^I */
                    407:                                break;
                    408:                        case 'C':
                    409:                                flags |= ONEOSEPONLY;
                    410:                        case 'S':
                    411:                                if (p[1])
                    412:                                        osep = *++p;
                    413:                                else
                    414:                                        osep = '\t';    /* default is ^I */
                    415:                                break;
                    416:                        case 'w':               /* window width, default 80 */
                    417:                                p = getnum(&owidth, p, 0);
                    418:                                if (owidth <= 0)
1.2       deraadt   419:                                usage("Width must be a positive integer", "");
1.1       deraadt   420:                                break;
                    421:                        case 'K':                       /* skip N lines */
                    422:                                flags |= SKIPPRINT;
                    423:                        case 'k':                       /* skip, do not print */
                    424:                                p = getnum(&skip, p, 0);
                    425:                                if (!skip)
                    426:                                        skip = 1;
                    427:                                break;
                    428:                        case 'm':
                    429:                                flags |= NOTRIMENDCOL;
                    430:                                break;
                    431:                        case 'g':               /* gutter space */
                    432:                                p = getnum(&gutter, p, 0);
                    433:                                break;
                    434:                        case 'G':
                    435:                                p = getnum(&propgutter, p, 0);
                    436:                                break;
                    437:                        case 'e':               /* each line is an entry */
                    438:                                flags |= ONEPERLINE;
                    439:                                break;
                    440:                        case 'E':
                    441:                                flags |= ONEPERCHAR;
                    442:                                break;
                    443:                        case 'j':                       /* right adjust */
                    444:                                flags |= RIGHTADJUST;
                    445:                                break;
                    446:                        case 'n':       /* null padding for missing values */
                    447:                                flags |= NULLPAD;
                    448:                                break;
                    449:                        case 'y':
                    450:                                flags |= RECYCLE;
                    451:                                break;
                    452:                        case 'H':                       /* print shape only */
                    453:                                flags |= DETAILSHAPE;
                    454:                        case 'h':
                    455:                                flags |= SHAPEONLY;
                    456:                                break;
                    457:                        case 'z':                       /* squeeze col width */
                    458:                                flags |= SQUEEZE;
                    459:                                break;
                    460:                        /*case 'p':
                    461:                                ipagespace = atoi(++p); (default is 1)
                    462:                                break;*/
                    463:                        case 'o':                       /* col order */
                    464:                                p = getlist(&cord, p);
                    465:                                break;
                    466:                        case 'b':
                    467:                                flags |= ICOLBOUNDS;
                    468:                                p = getlist(&icbd, p);
                    469:                                break;
                    470:                        case 'B':
                    471:                                flags |= OCOLBOUNDS;
                    472:                                p = getlist(&ocbd, p);
                    473:                                break;
                    474:                        default:
1.2       deraadt   475:                                usage("Bad flag:  %.1s", p);
1.1       deraadt   476:                        }
                    477:        /*if (!osep)
                    478:                osep = isep;*/
                    479:        switch (ac) {
                    480:        /*case 3:
                    481:                opages = atoi(av[2]);*/
                    482:        case 2:
                    483:                ocols = atoi(av[1]);
                    484:        case 1:
                    485:                orows = atoi(av[0]);
                    486:        case 0:
                    487:                break;
                    488:        default:
1.2       deraadt   489:                usage("Too many arguments.", "");
1.1       deraadt   490:        }
                    491: }
                    492:
                    493: char *
1.9       deraadt   494: getlist(short **list, char *p)
1.1       deraadt   495: {
1.6       mpech     496:        int count = 1;
                    497:        char *t;
1.1       deraadt   498:
                    499:        for (t = p + 1; *t; t++) {
                    500:                if (!isdigit(*t))
1.2       deraadt   501:                        usage("Option %.1s requires a list of unsigned numbers separated by commas", t);
1.1       deraadt   502:                count++;
                    503:                while (*t && isdigit(*t))
                    504:                        t++;
                    505:                if (*t != ',')
                    506:                        break;
                    507:        }
                    508:        if (!(*list = (short *) malloc(count * sizeof(short))))
1.2       deraadt   509:                errx(1, "No list space");
1.1       deraadt   510:        count = 0;
                    511:        for (t = p + 1; *t; t++) {
                    512:                (*list)[count++] = atoi(t);
                    513:                printf("++ %d ", (*list)[count-1]);
                    514:                fflush(stdout);
                    515:                while (*t && isdigit(*t))
                    516:                        t++;
                    517:                if (*t != ',')
                    518:                        break;
                    519:        }
                    520:        (*list)[count] = 0;
                    521:        return(t - 1);
                    522: }
                    523:
1.9       deraadt   524: /* num = number p points to; if (strict) complain */
                    525: /* returns pointer to end of num */
1.1       deraadt   526: char *
1.9       deraadt   527: getnum(int *num, char *p, int strict)
1.1       deraadt   528: {
1.6       mpech     529:        char *t = p;
1.1       deraadt   530:
                    531:        if (!isdigit(*++t)) {
                    532:                if (strict || *t == '-' || *t == '+')
1.2       deraadt   533:                        usage("Option %.1s requires an unsigned integer", p);
1.1       deraadt   534:                *num = 0;
                    535:                return(p);
                    536:        }
                    537:        *num = atoi(t);
                    538:        while (*++t)
                    539:                if (!isdigit(*t))
                    540:                        break;
                    541:        return(--t);
                    542: }