ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcollate.c
Revision: 2.41
Committed: Wed Mar 16 18:01:47 2022 UTC (2 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.40: +6 -7 lines
Log Message:
refactor(rcollate): A few minor changes that should not affect performance

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rcollate.c,v 2.40 2022/03/16 17:36:45 greg Exp $";
3 #endif
4 /*
5 * Utility to re-order records in a binary or ASCII data file (matrix)
6 */
7
8 #include <stdlib.h>
9 #include <ctype.h>
10 #include "platform.h"
11 #include "rtio.h"
12 #include "resolu.h"
13 #if defined(_WIN32) || defined(_WIN64)
14 #undef ftello
15 #define ftello ftell
16 #undef ssize_t
17 #define ssize_t size_t
18 #else
19 #include <sys/mman.h>
20 #endif
21
22 #define MAXLEVELS 16 /* max RxC.. block pairs */
23
24 typedef struct {
25 void *mapped; /* memory-mapped pointer */
26 void *base; /* pointer to base memory */
27 size_t len; /* allocated memory length */
28 } MEMLOAD; /* file loaded/mapped into memory */
29
30 typedef struct {
31 int nw_rec; /* number of words per record */
32 ssize_t nrecs; /* number of records we found */
33 char *rec[1]; /* record array (extends struct) */
34 } RECINDEX;
35
36 int warnings = 1; /* report warnings? */
37
38 char *fmtid = NULL; /* format id */
39 int comp_size = 0; /* binary bytes/channel */
40 int n_comp = 0; /* components/record */
41 int ni_columns = 0; /* number of input columns */
42 int ni_rows = 0; /* number of input rows */
43 int no_columns = 0; /* number of output columns */
44 int no_rows = 0; /* number of output rows */
45 int transpose = 0; /* transpose rows & cols? */
46 int i_header = 1; /* input header? */
47 int o_header = 1; /* output header? */
48 int outArray[MAXLEVELS][2]; /* output block nesting */
49 int outLevels = 0; /* number of blocking levels */
50 int check = 0; /* force data check? */
51
52 /* free loaded file */
53 static void
54 free_load(MEMLOAD *mp)
55 {
56 if (mp == NULL || (mp->base == NULL) | (mp->len <= 0))
57 return;
58 #ifdef MAP_FILE
59 if (mp->mapped)
60 munmap(mp->mapped, mp->len);
61 else
62 #endif
63 free(mp->base);
64 mp->mapped = NULL;
65 mp->base = NULL;
66 mp->len = 0;
67 }
68
69 /* load memory from an input stream, starting from current position */
70 static int
71 load_stream(MEMLOAD *mp, FILE *fp)
72 {
73 size_t alloced = 0;
74 char buf[8192];
75 size_t nr;
76
77 if (mp == NULL)
78 return(-1);
79 mp->mapped = NULL;
80 mp->base = NULL;
81 mp->len = 0;
82 if (fp == NULL)
83 return(-1);
84 while ((nr = fread(buf, 1, sizeof(buf), fp)) > 0) {
85 if (!alloced)
86 mp->base = malloc(alloced = nr);
87 else if (mp->len+nr > alloced)
88 mp->base = realloc(mp->base,
89 alloced = alloced*(2+(nr==sizeof(buf)))/2+nr);
90 if (mp->base == NULL)
91 return(-1);
92 memcpy((char *)mp->base + mp->len, buf, nr);
93 mp->len += nr;
94 }
95 if (ferror(fp)) {
96 free_load(mp);
97 return(-1);
98 }
99 if (alloced > mp->len*5/4) /* don't waste too much space */
100 mp->base = realloc(mp->base, mp->len);
101 return(mp->len > 0);
102 }
103
104 #if defined(_WIN32) || defined(_WIN64)
105 /* too difficult to fix this */
106 #define load_file load_stream
107 #else
108 /* load a file into memory */
109 static int
110 load_file(MEMLOAD *mp, FILE *fp)
111 {
112 int fd;
113 off_t skip, flen, fpos;
114 if (mp == NULL)
115 return(-1);
116 mp->mapped = NULL;
117 mp->base = NULL;
118 mp->len = 0;
119 if (fp == NULL)
120 return(-1);
121 fd = fileno(fp);
122 skip = ftello(fp);
123 flen = lseek(fd, 0, SEEK_END);
124 if (flen <= skip)
125 return((int)(flen - skip));
126 mp->len = (size_t)(flen - skip);
127 #ifdef MAP_FILE
128 if (mp->len >= 1L<<20) { /* map file if >= 1 MByte */
129 mp->mapped = mmap(NULL, flen, PROT_READ, MAP_PRIVATE, fd, 0);
130 if (mp->mapped != MAP_FAILED) {
131 mp->base = (char *)mp->mapped + skip;
132 return(1); /* mmap() success */
133 }
134 mp->mapped = NULL; /* else fall back to reading it in... */
135 }
136 #endif
137 if (lseek(fd, skip, SEEK_SET) != skip ||
138 (mp->base = malloc(mp->len)) == NULL) {
139 mp->len = 0;
140 return(-1);
141 }
142 fpos = skip;
143 while (fpos < flen) { /* read() fails if n > 2 GBytes */
144 ssize_t nread = read(fd, (char *)mp->base+(fpos-skip),
145 (flen-fpos < 1L<<24) ? flen-fpos : 1L<<24);
146 if (nread <= 0) {
147 free_load(mp);
148 return(-1);
149 }
150 fpos += nread;
151 }
152 return(1);
153 }
154 #endif
155
156 /* free a record index */
157 #define free_records(rp) free(rp)
158
159 /* compute record index */
160 static RECINDEX *
161 index_records(const MEMLOAD *mp, int nw_rec)
162 {
163 int nall = 0;
164 RECINDEX *rp;
165 char *cp, *mend;
166 int n;
167
168 if (mp == NULL || (mp->base == NULL) | (mp->len <= 0))
169 return(NULL);
170 if (nw_rec <= 0)
171 return(NULL);
172 nall = 1000;
173 rp = (RECINDEX *)malloc(sizeof(RECINDEX) + nall*sizeof(char *));
174 if (rp == NULL)
175 return(NULL);
176 rp->nw_rec = nw_rec;
177 rp->nrecs = 0;
178 cp = (char *)mp->base;
179 mend = cp + mp->len;
180 for ( ; ; ) { /* whitespace-separated words */
181 while (cp < mend && !*cp | isspace(*cp))
182 ++cp;
183 if (cp >= mend)
184 break;
185 if (rp->nrecs >= nall) {
186 nall += nall>>1; /* get more record space */
187 rp = (RECINDEX *)realloc(rp,
188 sizeof(RECINDEX) + nall*sizeof(char *));
189 if (rp == NULL)
190 return(NULL);
191 }
192 rp->rec[rp->nrecs++] = cp; /* point to first non-white */
193 n = rp->nw_rec;
194 while (++cp < mend) /* find end of record */
195 if (!*cp | isspace(*cp)) {
196 if (--n <= 0)
197 break; /* got requisite # words */
198 do { /* else find next word */
199 if (*cp == '\n') {
200 fputs("Unexpected EOL in record!\n", stderr);
201 free_records(rp);
202 return(NULL);
203 }
204 if (++cp >= mend)
205 break;
206 } while (!*cp | isspace(*cp));
207 }
208 }
209 rp->rec[rp->nrecs] = mend; /* reallocate to save space */
210 rp = (RECINDEX *)realloc(rp,
211 sizeof(RECINDEX) + rp->nrecs*sizeof(char *));
212 return(rp);
213 }
214
215 /* count number of columns based on first EOL */
216 static int
217 count_columns(const RECINDEX *rp)
218 {
219 char *cp = rp->rec[0];
220 char *mend = rp->rec[rp->nrecs];
221 int i;
222
223 while (*cp != '\n')
224 if (++cp >= mend)
225 return(0);
226 for (i = 0; i < rp->nrecs; i++)
227 if (rp->rec[i] >= cp)
228 break;
229 return(i);
230 }
231
232 /* copy nth record from index to stdout */
233 static int
234 print_record(const RECINDEX *rp, ssize_t n)
235 {
236 static char delims[] = " \t\n\r\f";
237 int words2go = rp->nw_rec;
238 char *scp;
239
240 if ((n < 0) | (n >= rp->nrecs))
241 return(0);
242 scp = rp->rec[n];
243
244 if (check && !isfltd(scp, delims))
245 goto formerr;
246 do {
247 putc(*scp++, stdout);
248 if (!*scp | isspace(*scp)) {
249 if (--words2go <= 0)
250 break;
251 putc(' ', stdout); /* single space btwn. words */
252 do
253 if (++scp >= rp->rec[n+1])
254 break;
255 while (!*scp | isspace(*scp));
256
257 if (check && !isfltd(scp, delims))
258 goto formerr;
259 }
260 } while (scp < rp->rec[n+1]);
261 /* caller adds record sep. */
262 return(1);
263 formerr:
264 fputs("Badly formed number: ", stderr);
265 while (*scp && !isspace(*scp))
266 fputc(*scp++, stderr);
267 fputc('\n', stderr);
268 return(0);
269 }
270
271 /* copy a stream to stdout */
272 static int
273 output_stream(FILE *fp)
274 {
275 char buf[8192];
276 ssize_t n;
277
278 if (fp == NULL)
279 return(0);
280 fflush(stdout);
281 while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
282 if (write(fileno(stdout), buf, n) != n)
283 return(0);
284 return(!ferror(fp));
285 }
286
287 /* get next word from stream, leaving stream on EOL or start of next word */
288 static char *
289 fget_word(char buf[256], FILE *fp)
290 {
291 int c;
292 char *cp;
293 /* skip nul's and white space */
294 while (!(c = getc(fp)) || isspace(c))
295 ;
296 if (c == EOF)
297 return(NULL);
298 cp = buf;
299 do
300 *cp++ = c;
301 while ((c = getc(fp)) != EOF && !isspace(c) && cp < buf+255);
302 *cp = '\0';
303 while (isspace(c) & (c != '\n'))
304 c = getc(fp);
305 if (c != EOF)
306 ungetc(c, fp);
307 return(buf);
308 }
309
310 /* parse RxCx... string */
311 static int
312 get_array(const char *spec, int blklvl[][2], int nlvls)
313 {
314 int n;
315
316 if (nlvls <= 0) {
317 fputs("Too many block levels!\n", stderr);
318 exit(1);
319 }
320 if (sscanf(spec, "%dx%d", &blklvl[0][0], &blklvl[0][1]) != 2) {
321 fputs("Bad block specification!\n", stderr);
322 exit(1);
323 }
324 while (isdigit(*spec))
325 spec++;
326 spec++; /* 'x' */
327 while (isdigit(*spec))
328 spec++;
329 if ((*spec != 'x') & (*spec != 'X')) {
330 if (*spec) {
331 fputs("Blocks must be separated by 'x' or 'X'\n", stderr);
332 exit(1);
333 }
334 return(1);
335 }
336 spec++;
337 n = get_array(spec, blklvl+1, nlvls-1);
338 if (!n)
339 return(0);
340 blklvl[0][0] *= blklvl[1][0];
341 blklvl[0][1] *= blklvl[1][1];
342 return(n+1);
343 }
344
345 /* check settings and assign defaults */
346 static int
347 check_sizes()
348 {
349 if (fmtid == NULL) {
350 fmtid = "ascii";
351 } else if (!comp_size) {
352 if (!strcmp(fmtid, "float"))
353 comp_size = sizeof(float);
354 else if (!strcmp(fmtid, "double"))
355 comp_size = sizeof(double);
356 else if (!strcmp(fmtid, "byte"))
357 comp_size = 1;
358 else if (strcmp(fmtid, "ascii")) {
359 fprintf(stderr, "Unsupported format: %s\n", fmtid);
360 return(0);
361 }
362 }
363 if (transpose && (no_rows <= 0) & (no_columns <= 0)) {
364 if (ni_rows > 0) no_columns = ni_rows;
365 if (ni_columns > 0) no_rows = ni_columns;
366 } else if ((no_rows <= 0) & (no_columns > 0) &&
367 !((ni_rows*ni_columns) % no_columns))
368 no_rows = ni_rows*ni_columns/no_columns;
369 if (n_comp <= 0)
370 n_comp = 3;
371 return(1);
372 }
373
374 /* call to compute block input position */
375 static ssize_t
376 get_block_pos(int r, int c, int blklvl[][2], int nlvls)
377 {
378 ssize_t n = 0;
379
380 while (nlvls > 1) {
381 int sr = r/blklvl[1][0];
382 int sc = c/blklvl[1][1];
383 r -= sr*blklvl[1][0];
384 c -= sc*blklvl[1][1];
385 n += sr*blklvl[1][0]*blklvl[0][1] + sc*blklvl[1][0]*blklvl[1][1];
386 blklvl++;
387 nlvls--;
388 }
389 n += r*blklvl[0][1] + c;
390 return(n);
391 }
392
393 /* return input offset based on array ordering and transpose option */
394 static ssize_t
395 get_input_pos(int r, int c)
396 {
397 ssize_t n;
398
399 if (outLevels > 1) { /* block reordering */
400 n = get_block_pos(r, c, outArray, outLevels);
401 if (transpose) {
402 r = n/ni_rows;
403 c = n - r*ni_rows;
404 n = (ssize_t)c*ni_columns + r;
405 }
406 } else if (transpose) /* transpose only */
407 n = (ssize_t)c*ni_columns + r;
408 else /* XXX should never happen! */
409 n = (ssize_t)r*no_columns + c;
410 return(n);
411 }
412
413 /* output reordered ASCII or binary data from memory */
414 static int
415 do_reorder(const MEMLOAD *mp)
416 {
417 static const char tabEOL[2] = {'\t','\n'};
418 RECINDEX *rp = NULL;
419 ssize_t nrecords;
420 int i, j;
421 /* propogate sizes */
422 if (ni_rows <= 0)
423 ni_rows = transpose ? no_columns : no_rows;
424 if (ni_columns <= 0)
425 ni_columns = transpose ? no_rows : no_columns;
426 /* get # records (& index) */
427 if (!comp_size) {
428 if ((rp = index_records(mp, n_comp)) == NULL)
429 return(0);
430 if (ni_columns <= 0)
431 ni_columns = count_columns(rp);
432 nrecords = rp->nrecs;
433 } else if ((ni_rows > 0) & (ni_columns > 0)) {
434 nrecords = (ssize_t)ni_rows*ni_columns;
435 if (nrecords > mp->len/(n_comp*comp_size)) {
436 fputs("Input too small for specified size and type\n",
437 stderr);
438 return(0);
439 }
440 } else
441 nrecords = mp->len/(n_comp*comp_size);
442 /* check sizes */
443 if ((ni_rows <= 0) & (ni_columns > 0))
444 ni_rows = nrecords/ni_columns;
445 else if ((ni_columns <= 0) & (ni_rows > 0))
446 ni_columns = nrecords/ni_rows;
447 if (nrecords != (ssize_t)ni_rows*ni_columns)
448 goto badspec;
449 if (transpose) {
450 if (no_columns <= 0)
451 no_columns = ni_rows;
452 if (no_rows <= 0)
453 no_rows = ni_columns;
454 if (outLevels <= 1 &&
455 (no_rows != ni_columns) | (no_columns != ni_rows))
456 goto badspec;
457 } else {
458 if (no_columns <= 0)
459 no_columns = ni_columns;
460 if (no_rows <= 0)
461 no_rows = ni_rows;
462 }
463 if (ni_rows*ni_columns != no_rows*no_columns) {
464 fputs("Number of input and output records do not match\n",
465 stderr);
466 return(0);
467 }
468 if (o_header) { /* finish header? */
469 printf("NROWS=%d\n", no_rows);
470 printf("NCOLS=%d\n", no_columns);
471 fputformat(fmtid, stdout);
472 fputc('\n', stdout);
473 }
474 /* reorder records */
475 for (i = 0; i < no_rows; i++) {
476 for (j = 0; j < no_columns; j++) {
477 ssize_t n = get_input_pos(i, j);
478 if (n >= nrecords) {
479 fputs("Index past end-of-file\n", stderr);
480 return(0);
481 }
482 if (rp != NULL) { /* ASCII output */
483 if (!print_record(rp, n))
484 return(0);
485 putc(tabEOL[j >= no_columns-1], stdout);
486 } else { /* binary output */
487 putbinary((char *)mp->base + (n_comp*comp_size)*n,
488 comp_size, n_comp, stdout);
489 }
490 }
491 if (ferror(stdout)) {
492 fputs("Error writing to stdout\n", stderr);
493 return(0);
494 }
495 }
496 if (rp != NULL)
497 free_records(rp);
498 return(1);
499 badspec:
500 fputs("Bad dimension(s)\n", stderr);
501 return(0);
502 }
503
504 /* resize stream input by ignoring EOLs between ASCII records */
505 static int
506 do_resize(FILE *fp)
507 {
508 ssize_t records2go = ni_rows*ni_columns;
509 int columns2go = no_columns;
510 char word[256];
511
512 if (o_header) { /* finish header? */
513 if (no_rows > 0)
514 printf("NROWS=%d\n", no_rows);
515 if (no_columns > 0)
516 printf("NCOLS=%d\n", no_columns);
517 fputformat(fmtid, stdout);
518 fputc('\n', stdout);
519 }
520 /* sanity checks */
521 if (comp_size || !check &
522 (no_columns == ni_columns) & (no_rows == ni_rows))
523 return(output_stream(fp)); /* no-op -- just copy */
524 if (no_columns <= 0) {
525 fputs("Missing -oc specification\n", stderr);
526 return(0);
527 }
528 if ((records2go <= 0) & (no_rows > 0))
529 records2go = no_rows*no_columns;
530 else if (no_rows*no_columns != records2go) {
531 fprintf(stderr,
532 "Number of input and output records disagree (%dx%d != %dx%d)\n",
533 ni_rows, ni_columns, no_rows, no_columns);
534 return(0);
535 }
536 do { /* reshape records */
537 int n;
538
539 for (n = n_comp; n--; ) {
540 if (fget_word(word, fp) == NULL) {
541 if (records2go > 0 || n < n_comp-1)
542 break;
543 goto done; /* normal EOD */
544 }
545 if (check && !isflt(word)) {
546 fputs("Badly formed number: ", stderr);
547 fputs(word, stderr);
548 fputc('\n', stderr);
549 return(0);
550 }
551 fputs(word, stdout);
552 if (n) { /* mid-record? */
553 int c = getc(fp);
554 if ((c == '\n') | (c == EOF))
555 break;
556 ungetc(c, fp);
557 putc(' ', stdout);
558 }
559 }
560 if (n >= 0) {
561 fputs("Incomplete record / unexpected EOF\n", stderr);
562 return(0);
563 }
564 if (--columns2go <= 0) { /* time to end output row? */
565 putc('\n', stdout);
566 columns2go = no_columns;
567 } else /* else separate records */
568 putc('\t', stdout);
569 } while (--records2go); /* expected EOD? */
570 done:
571 if (warnings && columns2go != no_columns)
572 fputs("Warning -- incomplete final row\n", stderr);
573 if (warnings && fget_word(word, fp) != NULL)
574 fputs("Warning -- characters beyond expected EOD\n", stderr);
575 return(1);
576 }
577
578 /* process a header line and copy to stdout */
579 static int
580 headline(char *s, void *p)
581 {
582 static char fmt[MAXFMTLEN];
583 int n;
584
585 if (formatval(fmt, s)) {
586 if (fmtid == NULL) {
587 fmtid = fmt;
588 return(0);
589 }
590 if (!strcmp(fmt, fmtid))
591 return(0);
592 fprintf(stderr, "Input format '%s' != '%s'\n", fmt, fmtid);
593 return(-1);
594 }
595 if (!strncmp(s, "NROWS=", 6)) {
596 n = atoi(s+6);
597 if ((ni_rows > 0) & (n != ni_rows)) {
598 fputs("Incorrect input row count\n", stderr);
599 return(-1);
600 }
601 ni_rows = n;
602 return(0);
603 }
604 if (!strncmp(s, "NCOLS=", 6)) {
605 n = atoi(s+6);
606 if ((ni_columns > 0) & (n != ni_columns)) {
607 fputs("Incorrect input column count\n", stderr);
608 return(-1);
609 }
610 ni_columns = n;
611 return(0);
612 }
613 if (!strncmp(s, "NCOMP=", 6)) {
614 n = atoi(s+6);
615 if ((n_comp > 0) & (n != n_comp)) {
616 fputs("Incorrect number of components\n", stderr);
617 return(-1);
618 }
619 n_comp = n;
620 return(0);
621 }
622 if (o_header)
623 fputs(s, stdout); /* copy header info. */
624 return(0);
625 }
626
627 /* main routine for converting rows/columns in data file */
628 int
629 main(int argc, char *argv[])
630 {
631 int a;
632
633 for (a = 1; a < argc && argv[a][0] == '-'; a++)
634 switch (argv[a][1]) {
635 case 'i': /* input */
636 if (argv[a][2] == 'c') /* columns */
637 ni_columns = atoi(argv[++a]);
638 else if (argv[a][2] == 'r')
639 ni_rows = atoi(argv[++a]);
640 else
641 goto userr;
642 break;
643 case 'o': /* output */
644 if (argv[a][2] == 'c') /* columns */
645 no_columns = atoi(argv[++a]);
646 else if (argv[a][2] == 'r')
647 no_rows = atoi(argv[++a]);
648 else if (argv[a][2] ||
649 !(outLevels=get_array(argv[++a], outArray, MAXLEVELS)))
650 goto userr;
651 break;
652 case 'h': /* turn off header */
653 switch (argv[a][2]) {
654 case 'i':
655 i_header = 0;
656 break;
657 case 'o':
658 o_header = 0;
659 break;
660 case '\0':
661 i_header = o_header = 0;
662 break;
663 default:
664 goto userr;
665 }
666 break;
667 case 't': /* transpose on/off */
668 transpose = !transpose;
669 break;
670 case 'f': /* format */
671 switch (argv[a][2]) {
672 case 'a': /* ASCII */
673 case 'A':
674 fmtid = "ascii";
675 comp_size = 0;
676 break;
677 case 'f': /* float */
678 case 'F':
679 fmtid = "float";
680 comp_size = sizeof(float);
681 break;
682 case 'd': /* double */
683 case 'D':
684 fmtid = "double";
685 comp_size = sizeof(double);
686 break;
687 case 'b': /* binary (bytes) */
688 case 'B':
689 fmtid = "byte";
690 comp_size = 1;
691 break;
692 default:
693 goto userr;
694 }
695 if (argv[a][3]) {
696 if (!isdigit(argv[a][3]))
697 goto userr;
698 n_comp = atoi(argv[a]+3);
699 } else
700 n_comp = 1;
701 break;
702 case 'w': /* warnings on/off */
703 warnings = !warnings;
704 break;
705 case 'c': /* force check operation */
706 check = 1;
707 break;
708 default:
709 goto userr;
710 }
711 if (a < argc-1) /* arg count OK? */
712 goto userr;
713 if (outLevels) { /* should check consistency? */
714 no_rows = outArray[0][0];
715 no_columns = outArray[0][1];
716 }
717 /* open input file? */
718 if (a == argc-1 && freopen(argv[a], "r", stdin) == NULL) {
719 fprintf(stderr, "%s: cannot open for reading\n", argv[a]);
720 return(1);
721 }
722 if (comp_size) {
723 SET_FILE_BINARY(stdin);
724 SET_FILE_BINARY(stdout);
725 }
726 #ifdef getc_unlocked /* avoid stupid semaphores */
727 flockfile(stdin);
728 flockfile(stdout);
729 #endif
730 /* check for no-op */
731 if (!transpose & !check & (outLevels <= 1) & (i_header == o_header) &&
732 (no_columns == ni_columns) & (no_rows == ni_rows)) {
733 if (warnings)
734 fprintf(stderr, "%s: no-op -- copying input verbatim\n",
735 argv[0]);
736 if (!output_stream(stdin))
737 return(1);
738 return(0);
739 }
740 if (i_header) { /* read header */
741 if (getheader(stdin, headline, NULL) < 0)
742 return(1);
743 if (!check_sizes())
744 return(1);
745 if (comp_size) { /* a little late... */
746 SET_FILE_BINARY(stdin);
747 SET_FILE_BINARY(stdout);
748 }
749 } else if (!check_sizes())
750 return(1);
751 if (o_header) { /* write/add to header */
752 if (!i_header)
753 newheader("RADIANCE", stdout);
754 printargs(a, argv, stdout);
755 printf("NCOMP=%d\n", n_comp);
756 }
757 if (transpose | check | (outLevels > 1) || (o_header && no_rows <= 0)) {
758 MEMLOAD myMem; /* need to map into memory */
759 if (a == argc-1) {
760 if (load_file(&myMem, stdin) <= 0) {
761 fprintf(stderr, "%s: error loading file into memory\n",
762 argv[a]);
763 return(1);
764 }
765 } else if (load_stream(&myMem, stdin) <= 0) {
766 fprintf(stderr, "%s: error loading stdin into memory\n",
767 argv[0]);
768 return(1);
769 }
770 if (!do_reorder(&myMem))
771 return(1);
772 /* free_load(&myMem); about to exit, so don't bother */
773 } else if (!do_resize(stdin)) /* just reshaping input */
774 return(1);
775 return(0);
776 userr:
777 fprintf(stderr,
778 "Usage: %s [-h[io]][-w][-c][-f[afdb][N]][-t][-ic in_col][-ir in_row][-oc out_col][-or out_row][-o RxC[xR1xC1..]] [input.dat]\n",
779 argv[0]);
780 return(1);
781 }