source: trunk/third/rs/rs.c @ 9110

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