1 /* $NetBSD: rs.c,v 1.13 2009/04/13 07:06:53 lukem Exp $ */
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
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
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)rs.c 8.1 (Berkeley) 6/6/93";
42 __RCSID("$NetBSD: rs.c,v 1.13 2009/04/13 07:06:53 lukem Exp $");
47 * rs - reshape a data array
48 * Author: John Kunze, Office of Comp. Affairs, UCB
49 * BEWARE: lots of unfinished edges
60 #define TRANSPOSE 000001
61 #define MTRANSPOSE 000002
62 #define ONEPERLINE 000004
63 #define ONEISEPONLY 000010
64 #define ONEOSEPONLY 000020
65 #define NOTRIMENDCOL 000040
66 #define SQUEEZE 000100
67 #define SHAPEONLY 000200
68 #define DETAILSHAPE 000400
69 #define RIGHTADJUST 001000
70 #define NULLPAD 002000
71 #define RECYCLE 004000
72 #define SKIPPRINT 010000
73 #define ICOLBOUNDS 020000
74 #define OCOLBOUNDS 040000
75 #define ONEPERCHAR 0100000
76 #define NOARGS 0200000
86 int allocsize
= BUFSIZ
;
93 char isep
= ' ', osep
= ' ';
94 int owidth
= 80, gutter
= 2;
96 void usage
__P((const char *, ...))
97 __attribute__((__format__(__printf__
, 1, 2)));
98 void getargs
__P((int, char *[]));
99 void getfile
__P((void));
100 int get_line
__P((void));
101 char *getlist
__P((short **, char *));
102 char *getnum
__P((int *, char *, int));
103 char **getptrs
__P((char **));
104 int main
__P((int, char **));
105 void prepfile
__P((void));
106 void prints
__P((char *, int));
107 void putfile
__P((void));
109 #define INCR(ep) do { \
110 if (++ep >= endelem) \
121 if (flags
& SHAPEONLY
) {
122 printf("%d %d\n", irows
, icols
);
133 char empty
[1] = { '\0' };
137 int multisep
= (flags
& ONEISEPONLY
? 0 : 1);
138 int nullpad
= flags
& NULLPAD
;
143 if (flags
& SKIPPRINT
)
147 if (flags
& NOARGS
&& curlen
< owidth
)
149 if (flags
& ONEPERLINE
)
151 else /* count cols on first line */
152 for (p
= curline
, endp
= curline
+ curlen
; p
< endp
; p
++) {
153 if (*p
== isep
&& multisep
)
156 while (*p
&& *p
!= isep
)
162 if (flags
& ONEPERLINE
) {
164 INCR(ep
); /* prepare for next entry */
170 for (p
= curline
, endp
= curline
+ curlen
; p
< endp
; p
++) {
171 if (*p
== isep
&& multisep
)
172 continue; /* eat up column separators */
173 if (*p
== isep
) /* must be an empty column */
175 else /* store column entry */
177 while (p
< endp
&& *p
!= isep
)
178 p
++; /* find end of entry */
179 *p
= '\0'; /* mark end of entry */
180 if (maxlen
< p
- *ep
) /* update maxlen */
182 INCR(ep
); /* prepare for next entry */
184 irows
++; /* update row count */
185 if (nullpad
) { /* pad missing entries */
186 padto
= elem
+ irows
* icols
;
192 } while (get_line() != EOF
);
193 *ep
= 0; /* mark end of pointers */
204 if (flags
& TRANSPOSE
) {
205 for (i
= 0; i
< orows
; i
++) {
206 for (j
= i
; j
< nelem
; j
+= orows
)
207 prints(ep
[j
], (j
- i
) / orows
);
211 for (n
= 0, i
= 0; i
< orows
&& n
< nelem
; i
++) {
212 for (j
= 0; j
< ocols
; j
++) {
232 n
= (flags
& ONEOSEPONLY
? 1 : colwidths
[col
] - (p
- s
));
233 if (flags
& RIGHTADJUST
)
243 usage(const char *msg
, ...)
251 "usage: rs [ -[csCS][x][kKgGw][N]tTeEnyjhHm ] [ rows [ cols ] ]\n");
269 gutter
+= maxlen
* propgutter
/ 100.0;
270 colw
= maxlen
+ gutter
;
271 if (flags
& MTRANSPOSE
) {
275 else if (orows
== 0 && ocols
== 0) { /* decide rows and cols */
276 ocols
= owidth
/ colw
;
278 warnx("Display width %d is less than column width %d", owidth
, colw
);
283 orows
= nelem
/ ocols
+ (nelem
% ocols
? 1 : 0);
285 else if (orows
== 0) /* decide on rows */
286 orows
= nelem
/ ocols
+ (nelem
% ocols
? 1 : 0);
287 else if (ocols
== 0) /* decide on cols */
288 ocols
= nelem
/ orows
+ (nelem
% orows
? 1 : 0);
289 lp
= elem
+ orows
* ocols
;
290 while (lp
> endelem
) {
291 getptrs(elem
+ nelem
);
292 lp
= elem
+ orows
* ocols
;
294 if (flags
& RECYCLE
) {
295 for (ep
= elem
+ nelem
; ep
< lp
; ep
++)
299 if (!(colwidths
= (short *) malloc(ocols
* sizeof(short))))
300 errx(1, "malloc: No gutter space");
301 if (flags
& SQUEEZE
) {
302 if (flags
& TRANSPOSE
)
303 for (ep
= elem
, i
= 0; i
< ocols
; i
++) {
304 for (j
= 0; j
< orows
; j
++)
305 if ((n
= strlen(*ep
++)) > max
)
307 colwidths
[i
] = max
+ gutter
;
310 for (ep
= elem
, i
= 0; i
< ocols
; i
++) {
311 for (j
= i
; j
< nelem
; j
+= ocols
)
312 if ((n
= strlen(ep
[j
])) > max
)
314 colwidths
[i
] = max
+ gutter
;
317 /* for (i = 0; i < orows; i++) {
318 for (j = i; j < nelem; j += orows)
319 prints(ep[j], (j - i) / orows);
323 for (i = 0; i < orows; i++) {
324 for (j = 0; j < ocols; j++)
329 for (i
= 0; i
< ocols
; i
++)
331 if (!(flags
& NOTRIMENDCOL
)) {
332 if (flags
& RIGHTADJUST
)
333 colwidths
[0] -= gutter
;
335 colwidths
[ocols
- 1] = 0;
338 if (n
> nelem
&& (flags
& RECYCLE
))
340 /*for (i = 0; i < ocols; i++)
341 fprintf(stderr, "%d ",colwidths[i]);
342 fprintf(stderr, "is colwidths, nelem %d\n", nelem);*/
346 char ibuf
[BSIZE
]; /* two screenfuls should do */
349 get_line() /* get line; maintain curline, curlen; manage storage */
351 static int putlength
;
352 static char *endblock
= ibuf
+ BSIZE
;
358 putlength
= flags
& DETAILSHAPE
;
360 else if (skip
<= 0) { /* don't waste storage */
361 curline
+= curlen
+ 1;
362 if (putlength
) /* print length, recycle storage */
363 printf(" %d line %d\n", curlen
, irows
);
365 if (!putlength
&& endblock
- curline
< BUFSIZ
) { /* need storage */
366 /*ww = endblock-curline; tt += ww;*/
367 /*printf("#wasted %d total %d\n",ww,tt);*/
368 if (!(curline
= (char *) malloc(BSIZE
)))
369 errx(1, "File too large");
370 endblock
= curline
+ BSIZE
;
371 /*printf("#endb %d curline %d\n",endblock,curline);*/
373 for (p
= curline
, i
= 1; i
< BUFSIZ
; *p
++ = c
, i
++)
374 if ((c
= getchar()) == EOF
|| c
== '\n')
387 allocsize
+= allocsize
;
388 p
= (char **)realloc(elem
, allocsize
* sizeof(char *));
393 endelem
= (elem
= p
) + allocsize
;
405 flags
|= NOARGS
| TRANSPOSE
;
407 while (--ac
&& **++av
== '-')
408 for (p
= *av
+1; *p
; p
++)
415 case 'c': /* input col. separator */
416 flags
|= ONEISEPONLY
;
417 case 's': /* one or more allowed */
421 isep
= '\t'; /* default is ^I */
424 flags
|= ONEOSEPONLY
;
429 osep
= '\t'; /* default is ^I */
431 case 'w': /* window width, default 80 */
432 p
= getnum(&owidth
, p
, 0);
434 usage("Width must be a positive integer");
436 case 'K': /* skip N lines */
438 case 'k': /* skip, do not print */
439 p
= getnum(&skip
, p
, 0);
444 flags
|= NOTRIMENDCOL
;
446 case 'g': /* gutter space */
447 p
= getnum(&gutter
, p
, 0);
450 p
= getnum(&propgutter
, p
, 0);
452 case 'e': /* each line is an entry */
458 case 'j': /* right adjust */
459 flags
|= RIGHTADJUST
;
461 case 'n': /* null padding for missing values */
467 case 'H': /* print shape only */
468 flags
|= DETAILSHAPE
;
472 case 'z': /* squeeze col width */
476 ipagespace = atoi(++p); (default is 1)
478 case 'o': /* col order */
479 p
= getlist(&cord
, p
);
483 p
= getlist(&icbd
, p
);
487 p
= getlist(&ocbd
, p
);
490 usage("Bad flag: %.1s", p
);
496 opages = atoi(av[2]);*/
504 usage("Too many arguments.");
516 for (t
= p
+ 1; *t
; t
++) {
517 if (!isdigit((unsigned char)*t
))
518 usage("Option %.1s requires a list of unsigned numbers separated by commas", t
);
520 while (*t
&& isdigit((unsigned char)*t
))
525 if (!(*list
= (short *) malloc(count
* sizeof(short))))
526 errx(1, "No list space");
528 for (t
= p
+ 1; *t
; t
++) {
529 (*list
)[count
++] = atoi(t
);
530 printf("++ %d ", (*list
)[count
-1]);
532 while (*t
&& isdigit((unsigned char)*t
))
542 getnum(num
, p
, strict
) /* num = number p points to; if (strict) complain */
543 int *num
, strict
; /* returns pointer to end of num */
548 if (!isdigit((unsigned char)*++t
)) {
549 if (strict
|| *t
== '-' || *t
== '+')
550 usage("Option %.1s requires an unsigned integer", p
);
556 if (!isdigit((unsigned char)*t
))