|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.