Deleted Added
full compact
rs.c (145617) rs.c (181278)
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 const 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 const 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 <sys/cdefs.h>
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 const 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 const 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 <sys/cdefs.h>
51__FBSDID("$FreeBSD: head/usr.bin/rs/rs.c 145617 2005-04-28 12:37:15Z robert $");
51__FBSDID("$FreeBSD: head/usr.bin/rs/rs.c 181278 2008-08-04 06:39:52Z cperciva $");
52
53#include <err.h>
54#include <ctype.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <string.h>
58
59long flags;
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
77
78short *colwidths;
79short *cord;
80short *icbd;
81short *ocbd;
82int nelem;
83char **elem;
84char **endelem;
85char *curline;
86int allocsize = BUFSIZ;
87int curlen;
88int irows, icols;
89int orows = 0, ocols = 0;
90int maxlen;
91int skip;
92int propgutter;
93char isep = ' ', osep = ' ';
94char blank[] = "";
95int owidth = 80, gutter = 2;
96
97void getargs(int, char *[]);
98void getfile(void);
99int getline(void);
100char *getlist(short **, char *);
101char *getnum(int *, char *, int);
102char **getptrs(char **);
103void prepfile(void);
104void prints(char *, int);
105void putfile(void);
106static void usage(void);
107
108#define INCR(ep) do { \
109 if (++ep >= endelem) \
110 ep = getptrs(ep); \
111} while(0)
112
113int
114main(int argc, char *argv[])
115{
116 getargs(argc, argv);
117 getfile();
118 if (flags & SHAPEONLY) {
119 printf("%d %d\n", irows, icols);
120 exit(0);
121 }
122 prepfile();
123 putfile();
124 exit(0);
125}
126
127void
128getfile(void)
129{
130 char *p;
131 char *endp;
132 char **ep;
133 int multisep = (flags & ONEISEPONLY ? 0 : 1);
134 int nullpad = flags & NULLPAD;
135 char **padto;
136
137 while (skip--) {
138 getline();
139 if (flags & SKIPPRINT)
140 puts(curline);
141 }
142 getline();
143 if (flags & NOARGS && curlen < owidth)
144 flags |= ONEPERLINE;
145 if (flags & ONEPERLINE)
146 icols = 1;
147 else /* count cols on first line */
148 for (p = curline, endp = curline + curlen; p < endp; p++) {
149 if (*p == isep && multisep)
150 continue;
151 icols++;
152 while (*p && *p != isep)
153 p++;
154 }
155 ep = getptrs(elem);
52
53#include <err.h>
54#include <ctype.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <string.h>
58
59long flags;
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
77
78short *colwidths;
79short *cord;
80short *icbd;
81short *ocbd;
82int nelem;
83char **elem;
84char **endelem;
85char *curline;
86int allocsize = BUFSIZ;
87int curlen;
88int irows, icols;
89int orows = 0, ocols = 0;
90int maxlen;
91int skip;
92int propgutter;
93char isep = ' ', osep = ' ';
94char blank[] = "";
95int owidth = 80, gutter = 2;
96
97void getargs(int, char *[]);
98void getfile(void);
99int getline(void);
100char *getlist(short **, char *);
101char *getnum(int *, char *, int);
102char **getptrs(char **);
103void prepfile(void);
104void prints(char *, int);
105void putfile(void);
106static void usage(void);
107
108#define INCR(ep) do { \
109 if (++ep >= endelem) \
110 ep = getptrs(ep); \
111} while(0)
112
113int
114main(int argc, char *argv[])
115{
116 getargs(argc, argv);
117 getfile();
118 if (flags & SHAPEONLY) {
119 printf("%d %d\n", irows, icols);
120 exit(0);
121 }
122 prepfile();
123 putfile();
124 exit(0);
125}
126
127void
128getfile(void)
129{
130 char *p;
131 char *endp;
132 char **ep;
133 int multisep = (flags & ONEISEPONLY ? 0 : 1);
134 int nullpad = flags & NULLPAD;
135 char **padto;
136
137 while (skip--) {
138 getline();
139 if (flags & SKIPPRINT)
140 puts(curline);
141 }
142 getline();
143 if (flags & NOARGS && curlen < owidth)
144 flags |= ONEPERLINE;
145 if (flags & ONEPERLINE)
146 icols = 1;
147 else /* count cols on first line */
148 for (p = curline, endp = curline + curlen; p < endp; p++) {
149 if (*p == isep && multisep)
150 continue;
151 icols++;
152 while (*p && *p != isep)
153 p++;
154 }
155 ep = getptrs(elem);
156 p = curline;
157 do {
158 if (flags & ONEPERLINE) {
159 *ep = curline;
160 INCR(ep); /* prepare for next entry */
161 if (maxlen < curlen)
162 maxlen = curlen;
163 irows++;
164 continue;
165 }
166 for (p = curline, endp = curline + curlen; p < endp; p++) {
167 if (*p == isep && multisep)
168 continue; /* eat up column separators */
169 if (*p == isep) /* must be an empty column */
170 *ep = blank;
171 else /* store column entry */
172 *ep = p;
173 while (p < endp && *p != isep)
174 p++; /* find end of entry */
175 *p = '\0'; /* mark end of entry */
176 if (maxlen < p - *ep) /* update maxlen */
177 maxlen = p - *ep;
178 INCR(ep); /* prepare for next entry */
179 }
180 irows++; /* update row count */
181 if (nullpad) { /* pad missing entries */
182 padto = elem + irows * icols;
183 while (ep < padto) {
184 *ep = blank;
185 INCR(ep);
186 }
187 }
188 } while (getline() != EOF);
189 *ep = 0; /* mark end of pointers */
190 nelem = ep - elem;
191}
192
193void
194putfile(void)
195{
196 char **ep;
197 int i, j, k;
198
199 ep = elem;
200 if (flags & TRANSPOSE)
201 for (i = 0; i < orows; i++) {
202 for (j = i; j < nelem; j += orows)
203 prints(ep[j], (j - i) / orows);
204 putchar('\n');
205 }
206 else
207 for (i = k = 0; i < orows; i++) {
208 for (j = 0; j < ocols; j++, k++)
209 if (k < nelem)
210 prints(ep[k], j);
211 putchar('\n');
212 }
213}
214
215void
216prints(char *s, int col)
217{
218 int n;
219 char *p = s;
220
221 while (*p)
222 p++;
223 n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
224 if (flags & RIGHTADJUST)
225 while (n-- > 0)
226 putchar(osep);
227 for (p = s; *p; p++)
228 putchar(*p);
229 while (n-- > 0)
230 putchar(osep);
231}
232
233static void
234usage(void)
235{
236 fprintf(stderr,
237 "usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n");
238 exit(1);
239}
240
241void
242prepfile(void)
243{
244 char **ep;
245 int i;
246 int j;
247 char **lp;
248 int colw;
249 int max;
250 int n;
251
252 if (!nelem)
253 exit(0);
254 gutter += maxlen * propgutter / 100.0;
255 colw = maxlen + gutter;
256 if (flags & MTRANSPOSE) {
257 orows = icols;
258 ocols = irows;
259 }
260 else if (orows == 0 && ocols == 0) { /* decide rows and cols */
261 ocols = owidth / colw;
262 if (ocols == 0) {
263 warnx("display width %d is less than column width %d",
264 owidth, colw);
265 ocols = 1;
266 }
267 if (ocols > nelem)
268 ocols = nelem;
269 orows = nelem / ocols + (nelem % ocols ? 1 : 0);
270 }
271 else if (orows == 0) /* decide on rows */
272 orows = nelem / ocols + (nelem % ocols ? 1 : 0);
273 else if (ocols == 0) /* decide on cols */
274 ocols = nelem / orows + (nelem % orows ? 1 : 0);
275 lp = elem + orows * ocols;
276 while (lp > endelem) {
277 getptrs(elem + nelem);
278 lp = elem + orows * ocols;
279 }
280 if (flags & RECYCLE) {
281 for (ep = elem + nelem; ep < lp; ep++)
282 *ep = *(ep - nelem);
283 nelem = lp - elem;
284 }
285 if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
286 errx(1, "malloc");
287 if (flags & SQUEEZE) {
288 ep = elem;
289 if (flags & TRANSPOSE)
290 for (i = 0; i < ocols; i++) {
291 max = 0;
292 for (j = 0; *ep != NULL && j < orows; j++)
293 if ((n = strlen(*ep++)) > max)
294 max = n;
295 colwidths[i] = max + gutter;
296 }
297 else
298 for (i = 0; i < ocols; i++) {
299 max = 0;
300 for (j = i; j < nelem; j += ocols)
301 if ((n = strlen(ep[j])) > max)
302 max = n;
303 colwidths[i] = max + gutter;
304 }
305 }
306 /* for (i = 0; i < orows; i++) {
307 for (j = i; j < nelem; j += orows)
308 prints(ep[j], (j - i) / orows);
309 putchar('\n');
310 }
311 else
312 for (i = 0; i < orows; i++) {
313 for (j = 0; j < ocols; j++)
314 prints(*ep++, j);
315 putchar('\n');
316 }*/
317 else
318 for (i = 0; i < ocols; i++)
319 colwidths[i] = colw;
320 if (!(flags & NOTRIMENDCOL)) {
321 if (flags & RIGHTADJUST)
322 colwidths[0] -= gutter;
323 else
324 colwidths[ocols - 1] = 0;
325 }
326 n = orows * ocols;
327 if (n > nelem && (flags & RECYCLE))
328 nelem = n;
329 /*for (i = 0; i < ocols; i++)
330 warnx("%d is colwidths, nelem %d", colwidths[i], nelem);*/
331}
332
333#define BSIZE 2048
334char ibuf[BSIZE]; /* two screenfuls should do */
335
336int
337getline(void) /* get line; maintain curline, curlen; manage storage */
338{
339 static int putlength;
340 static char *endblock = ibuf + BSIZE;
341 char *p;
342 int c, i;
343
344 if (!irows) {
345 curline = ibuf;
346 putlength = flags & DETAILSHAPE;
347 }
348 else if (skip <= 0) { /* don't waste storage */
349 curline += curlen + 1;
350 if (putlength) { /* print length, recycle storage */
351 printf(" %d line %d\n", curlen, irows);
352 curline = ibuf;
353 }
354 }
355 if (!putlength && endblock - curline < BUFSIZ) { /* need storage */
356 /*ww = endblock-curline; tt += ww;*/
357 /*printf("#wasted %d total %d\n",ww,tt);*/
358 if (!(curline = (char *) malloc(BSIZE)))
359 errx(1, "file too large");
360 endblock = curline + BSIZE;
361 /*printf("#endb %d curline %d\n",endblock,curline);*/
362 }
363 for (p = curline, i = 1; i < BUFSIZ; *p++ = c, i++)
364 if ((c = getchar()) == EOF || c == '\n')
365 break;
366 *p = '\0';
367 curlen = i - 1;
368 return(c);
369}
370
371char **
372getptrs(char **sp)
373{
374 char **p;
375
376 allocsize += allocsize;
377 p = (char **)realloc(elem, allocsize * sizeof(char *));
378 if (p == NULL)
379 err(1, "no memory");
380
381 sp += (p - elem);
382 endelem = (elem = p) + allocsize;
383 return(sp);
384}
385
386void
387getargs(int ac, char *av[])
388{
389 char *p;
390
391 if (ac == 1) {
392 flags |= NOARGS | TRANSPOSE;
393 }
394 while (--ac && **++av == '-')
395 for (p = *av+1; *p; p++)
396 switch (*p) {
397 case 'T':
398 flags |= MTRANSPOSE;
399 case 't':
400 flags |= TRANSPOSE;
401 break;
402 case 'c': /* input col. separator */
403 flags |= ONEISEPONLY;
404 case 's': /* one or more allowed */
405 if (p[1])
406 isep = *++p;
407 else
408 isep = '\t'; /* default is ^I */
409 break;
410 case 'C':
411 flags |= ONEOSEPONLY;
412 case 'S':
413 if (p[1])
414 osep = *++p;
415 else
416 osep = '\t'; /* default is ^I */
417 break;
418 case 'w': /* window width, default 80 */
419 p = getnum(&owidth, p, 0);
420 if (owidth <= 0)
421 errx(1, "width must be a positive integer");
422 break;
423 case 'K': /* skip N lines */
424 flags |= SKIPPRINT;
425 case 'k': /* skip, do not print */
426 p = getnum(&skip, p, 0);
427 if (!skip)
428 skip = 1;
429 break;
430 case 'm':
431 flags |= NOTRIMENDCOL;
432 break;
433 case 'g': /* gutter space */
434 p = getnum(&gutter, p, 0);
435 break;
436 case 'G':
437 p = getnum(&propgutter, p, 0);
438 break;
439 case 'e': /* each line is an entry */
440 flags |= ONEPERLINE;
441 break;
442 case 'E':
443 flags |= ONEPERCHAR;
444 break;
445 case 'j': /* right adjust */
446 flags |= RIGHTADJUST;
447 break;
448 case 'n': /* null padding for missing values */
449 flags |= NULLPAD;
450 break;
451 case 'y':
452 flags |= RECYCLE;
453 break;
454 case 'H': /* print shape only */
455 flags |= DETAILSHAPE;
456 case 'h':
457 flags |= SHAPEONLY;
458 break;
459 case 'z': /* squeeze col width */
460 flags |= SQUEEZE;
461 break;
462 /*case 'p':
463 ipagespace = atoi(++p); (default is 1)
464 break;*/
465 case 'o': /* col order */
466 p = getlist(&cord, p);
467 break;
468 case 'b':
469 flags |= ICOLBOUNDS;
470 p = getlist(&icbd, p);
471 break;
472 case 'B':
473 flags |= OCOLBOUNDS;
474 p = getlist(&ocbd, p);
475 break;
476 default:
477 usage();
478 }
479 /*if (!osep)
480 osep = isep;*/
481 switch (ac) {
482 /*case 3:
483 opages = atoi(av[2]);*/
484 case 2:
485 if ((ocols = atoi(av[1])) < 0)
486 ocols = 0;
487 case 1:
488 if ((orows = atoi(av[0])) < 0)
489 orows = 0;
490 case 0:
491 break;
492 default:
493 errx(1, "too many arguments");
494 }
495}
496
497char *
498getlist(short **list, char *p)
499{
500 int count = 1;
501 char *t;
502
503 for (t = p + 1; *t; t++) {
504 if (!isdigit((unsigned char)*t))
505 errx(1,
506 "option %.1s requires a list of unsigned numbers separated by commas", t);
507 count++;
508 while (*t && isdigit((unsigned char)*t))
509 t++;
510 if (*t != ',')
511 break;
512 }
513 if (!(*list = (short *) malloc(count * sizeof(short))))
514 errx(1, "no list space");
515 count = 0;
516 for (t = p + 1; *t; t++) {
517 (*list)[count++] = atoi(t);
518 printf("++ %d ", (*list)[count-1]);
519 fflush(stdout);
520 while (*t && isdigit((unsigned char)*t))
521 t++;
522 if (*t != ',')
523 break;
524 }
525 (*list)[count] = 0;
526 return(t - 1);
527}
528
529/*
530 * num = number p points to; if (strict) complain
531 * returns pointer to end of num
532 */
533char *
534getnum(int *num, char *p, int strict)
535{
536 char *t = p;
537
538 if (!isdigit((unsigned char)*++t)) {
539 if (strict || *t == '-' || *t == '+')
540 errx(1, "option %.1s requires an unsigned integer", p);
541 *num = 0;
542 return(p);
543 }
544 *num = atoi(t);
545 while (*++t)
546 if (!isdigit((unsigned char)*t))
547 break;
548 return(--t);
549}
156 do {
157 if (flags & ONEPERLINE) {
158 *ep = curline;
159 INCR(ep); /* prepare for next entry */
160 if (maxlen < curlen)
161 maxlen = curlen;
162 irows++;
163 continue;
164 }
165 for (p = curline, endp = curline + curlen; p < endp; p++) {
166 if (*p == isep && multisep)
167 continue; /* eat up column separators */
168 if (*p == isep) /* must be an empty column */
169 *ep = blank;
170 else /* store column entry */
171 *ep = p;
172 while (p < endp && *p != isep)
173 p++; /* find end of entry */
174 *p = '\0'; /* mark end of entry */
175 if (maxlen < p - *ep) /* update maxlen */
176 maxlen = p - *ep;
177 INCR(ep); /* prepare for next entry */
178 }
179 irows++; /* update row count */
180 if (nullpad) { /* pad missing entries */
181 padto = elem + irows * icols;
182 while (ep < padto) {
183 *ep = blank;
184 INCR(ep);
185 }
186 }
187 } while (getline() != EOF);
188 *ep = 0; /* mark end of pointers */
189 nelem = ep - elem;
190}
191
192void
193putfile(void)
194{
195 char **ep;
196 int i, j, k;
197
198 ep = elem;
199 if (flags & TRANSPOSE)
200 for (i = 0; i < orows; i++) {
201 for (j = i; j < nelem; j += orows)
202 prints(ep[j], (j - i) / orows);
203 putchar('\n');
204 }
205 else
206 for (i = k = 0; i < orows; i++) {
207 for (j = 0; j < ocols; j++, k++)
208 if (k < nelem)
209 prints(ep[k], j);
210 putchar('\n');
211 }
212}
213
214void
215prints(char *s, int col)
216{
217 int n;
218 char *p = s;
219
220 while (*p)
221 p++;
222 n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
223 if (flags & RIGHTADJUST)
224 while (n-- > 0)
225 putchar(osep);
226 for (p = s; *p; p++)
227 putchar(*p);
228 while (n-- > 0)
229 putchar(osep);
230}
231
232static void
233usage(void)
234{
235 fprintf(stderr,
236 "usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n");
237 exit(1);
238}
239
240void
241prepfile(void)
242{
243 char **ep;
244 int i;
245 int j;
246 char **lp;
247 int colw;
248 int max;
249 int n;
250
251 if (!nelem)
252 exit(0);
253 gutter += maxlen * propgutter / 100.0;
254 colw = maxlen + gutter;
255 if (flags & MTRANSPOSE) {
256 orows = icols;
257 ocols = irows;
258 }
259 else if (orows == 0 && ocols == 0) { /* decide rows and cols */
260 ocols = owidth / colw;
261 if (ocols == 0) {
262 warnx("display width %d is less than column width %d",
263 owidth, colw);
264 ocols = 1;
265 }
266 if (ocols > nelem)
267 ocols = nelem;
268 orows = nelem / ocols + (nelem % ocols ? 1 : 0);
269 }
270 else if (orows == 0) /* decide on rows */
271 orows = nelem / ocols + (nelem % ocols ? 1 : 0);
272 else if (ocols == 0) /* decide on cols */
273 ocols = nelem / orows + (nelem % orows ? 1 : 0);
274 lp = elem + orows * ocols;
275 while (lp > endelem) {
276 getptrs(elem + nelem);
277 lp = elem + orows * ocols;
278 }
279 if (flags & RECYCLE) {
280 for (ep = elem + nelem; ep < lp; ep++)
281 *ep = *(ep - nelem);
282 nelem = lp - elem;
283 }
284 if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
285 errx(1, "malloc");
286 if (flags & SQUEEZE) {
287 ep = elem;
288 if (flags & TRANSPOSE)
289 for (i = 0; i < ocols; i++) {
290 max = 0;
291 for (j = 0; *ep != NULL && j < orows; j++)
292 if ((n = strlen(*ep++)) > max)
293 max = n;
294 colwidths[i] = max + gutter;
295 }
296 else
297 for (i = 0; i < ocols; i++) {
298 max = 0;
299 for (j = i; j < nelem; j += ocols)
300 if ((n = strlen(ep[j])) > max)
301 max = n;
302 colwidths[i] = max + gutter;
303 }
304 }
305 /* for (i = 0; i < orows; i++) {
306 for (j = i; j < nelem; j += orows)
307 prints(ep[j], (j - i) / orows);
308 putchar('\n');
309 }
310 else
311 for (i = 0; i < orows; i++) {
312 for (j = 0; j < ocols; j++)
313 prints(*ep++, j);
314 putchar('\n');
315 }*/
316 else
317 for (i = 0; i < ocols; i++)
318 colwidths[i] = colw;
319 if (!(flags & NOTRIMENDCOL)) {
320 if (flags & RIGHTADJUST)
321 colwidths[0] -= gutter;
322 else
323 colwidths[ocols - 1] = 0;
324 }
325 n = orows * ocols;
326 if (n > nelem && (flags & RECYCLE))
327 nelem = n;
328 /*for (i = 0; i < ocols; i++)
329 warnx("%d is colwidths, nelem %d", colwidths[i], nelem);*/
330}
331
332#define BSIZE 2048
333char ibuf[BSIZE]; /* two screenfuls should do */
334
335int
336getline(void) /* get line; maintain curline, curlen; manage storage */
337{
338 static int putlength;
339 static char *endblock = ibuf + BSIZE;
340 char *p;
341 int c, i;
342
343 if (!irows) {
344 curline = ibuf;
345 putlength = flags & DETAILSHAPE;
346 }
347 else if (skip <= 0) { /* don't waste storage */
348 curline += curlen + 1;
349 if (putlength) { /* print length, recycle storage */
350 printf(" %d line %d\n", curlen, irows);
351 curline = ibuf;
352 }
353 }
354 if (!putlength && endblock - curline < BUFSIZ) { /* need storage */
355 /*ww = endblock-curline; tt += ww;*/
356 /*printf("#wasted %d total %d\n",ww,tt);*/
357 if (!(curline = (char *) malloc(BSIZE)))
358 errx(1, "file too large");
359 endblock = curline + BSIZE;
360 /*printf("#endb %d curline %d\n",endblock,curline);*/
361 }
362 for (p = curline, i = 1; i < BUFSIZ; *p++ = c, i++)
363 if ((c = getchar()) == EOF || c == '\n')
364 break;
365 *p = '\0';
366 curlen = i - 1;
367 return(c);
368}
369
370char **
371getptrs(char **sp)
372{
373 char **p;
374
375 allocsize += allocsize;
376 p = (char **)realloc(elem, allocsize * sizeof(char *));
377 if (p == NULL)
378 err(1, "no memory");
379
380 sp += (p - elem);
381 endelem = (elem = p) + allocsize;
382 return(sp);
383}
384
385void
386getargs(int ac, char *av[])
387{
388 char *p;
389
390 if (ac == 1) {
391 flags |= NOARGS | TRANSPOSE;
392 }
393 while (--ac && **++av == '-')
394 for (p = *av+1; *p; p++)
395 switch (*p) {
396 case 'T':
397 flags |= MTRANSPOSE;
398 case 't':
399 flags |= TRANSPOSE;
400 break;
401 case 'c': /* input col. separator */
402 flags |= ONEISEPONLY;
403 case 's': /* one or more allowed */
404 if (p[1])
405 isep = *++p;
406 else
407 isep = '\t'; /* default is ^I */
408 break;
409 case 'C':
410 flags |= ONEOSEPONLY;
411 case 'S':
412 if (p[1])
413 osep = *++p;
414 else
415 osep = '\t'; /* default is ^I */
416 break;
417 case 'w': /* window width, default 80 */
418 p = getnum(&owidth, p, 0);
419 if (owidth <= 0)
420 errx(1, "width must be a positive integer");
421 break;
422 case 'K': /* skip N lines */
423 flags |= SKIPPRINT;
424 case 'k': /* skip, do not print */
425 p = getnum(&skip, p, 0);
426 if (!skip)
427 skip = 1;
428 break;
429 case 'm':
430 flags |= NOTRIMENDCOL;
431 break;
432 case 'g': /* gutter space */
433 p = getnum(&gutter, p, 0);
434 break;
435 case 'G':
436 p = getnum(&propgutter, p, 0);
437 break;
438 case 'e': /* each line is an entry */
439 flags |= ONEPERLINE;
440 break;
441 case 'E':
442 flags |= ONEPERCHAR;
443 break;
444 case 'j': /* right adjust */
445 flags |= RIGHTADJUST;
446 break;
447 case 'n': /* null padding for missing values */
448 flags |= NULLPAD;
449 break;
450 case 'y':
451 flags |= RECYCLE;
452 break;
453 case 'H': /* print shape only */
454 flags |= DETAILSHAPE;
455 case 'h':
456 flags |= SHAPEONLY;
457 break;
458 case 'z': /* squeeze col width */
459 flags |= SQUEEZE;
460 break;
461 /*case 'p':
462 ipagespace = atoi(++p); (default is 1)
463 break;*/
464 case 'o': /* col order */
465 p = getlist(&cord, p);
466 break;
467 case 'b':
468 flags |= ICOLBOUNDS;
469 p = getlist(&icbd, p);
470 break;
471 case 'B':
472 flags |= OCOLBOUNDS;
473 p = getlist(&ocbd, p);
474 break;
475 default:
476 usage();
477 }
478 /*if (!osep)
479 osep = isep;*/
480 switch (ac) {
481 /*case 3:
482 opages = atoi(av[2]);*/
483 case 2:
484 if ((ocols = atoi(av[1])) < 0)
485 ocols = 0;
486 case 1:
487 if ((orows = atoi(av[0])) < 0)
488 orows = 0;
489 case 0:
490 break;
491 default:
492 errx(1, "too many arguments");
493 }
494}
495
496char *
497getlist(short **list, char *p)
498{
499 int count = 1;
500 char *t;
501
502 for (t = p + 1; *t; t++) {
503 if (!isdigit((unsigned char)*t))
504 errx(1,
505 "option %.1s requires a list of unsigned numbers separated by commas", t);
506 count++;
507 while (*t && isdigit((unsigned char)*t))
508 t++;
509 if (*t != ',')
510 break;
511 }
512 if (!(*list = (short *) malloc(count * sizeof(short))))
513 errx(1, "no list space");
514 count = 0;
515 for (t = p + 1; *t; t++) {
516 (*list)[count++] = atoi(t);
517 printf("++ %d ", (*list)[count-1]);
518 fflush(stdout);
519 while (*t && isdigit((unsigned char)*t))
520 t++;
521 if (*t != ',')
522 break;
523 }
524 (*list)[count] = 0;
525 return(t - 1);
526}
527
528/*
529 * num = number p points to; if (strict) complain
530 * returns pointer to end of num
531 */
532char *
533getnum(int *num, char *p, int strict)
534{
535 char *t = p;
536
537 if (!isdigit((unsigned char)*++t)) {
538 if (strict || *t == '-' || *t == '+')
539 errx(1, "option %.1s requires an unsigned integer", p);
540 *num = 0;
541 return(p);
542 }
543 *num = atoi(t);
544 while (*++t)
545 if (!isdigit((unsigned char)*t))
546 break;
547 return(--t);
548}