ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.14
Committed: Sun Apr 5 02:25:22 2020 UTC (4 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.13: +18 -15 lines
Log Message:
Fixed issue with duplicate, incorrect headers if '-' used more than once

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rsplit.c,v 1.13 2020/04/04 16:23:00 greg Exp $";
3 #endif
4 /*
5 * rsplit.c - split input into multiple output streams
6 *
7 * 7/4/19 Greg Ward
8 */
9
10 #include <ctype.h>
11
12 #include "rtio.h"
13 #include "platform.h"
14 #include "paths.h"
15 #include "resolu.h"
16
17 #define DOHEADER 1
18 #define DORESOLU 2
19
20 #define MAXFILE 512 /* maximum number of files */
21
22 static int swapped = 0; /* input is byte-swapped */
23
24 static FILE *output[MAXFILE];
25 static int ncomp[MAXFILE];
26 static int bytsiz[MAXFILE];
27 static int hdrflags[MAXFILE];
28 static const char *format[MAXFILE];
29 static int termc[MAXFILE];
30 static int nfiles = 0;
31
32 static RESOLU ourres = {PIXSTANDARD, 0, 0};
33
34 static char buf[16384]; /* input buffer used in scanOK() */
35
36
37 /* process header line */
38 static int
39 headline(char *s, void *p)
40 {
41 extern const char FMTSTR[];
42 int i;
43
44 if (strstr(s, FMTSTR) == s)
45 return(0); /* don't copy format */
46 if (!strncmp(s, "NROWS=", 6))
47 return(0);
48 if (!strncmp(s, "NCOLS=", 6))
49 return(0);
50 if (!strncmp(s, "NCOMP=", 6))
51 return(0);
52 if ((i = isbigendian(s)) >= 0) {
53 swapped = (nativebigendian() != i);
54 return(0);
55 }
56 i = nfiles;
57 while (i--) /* else copy line to output streams */
58 if (hdrflags[i] & DOHEADER)
59 fputs(s, output[i]);
60 return(1);
61 }
62
63
64 /* scan field into buffer up to and including terminating byte */
65 static int
66 scanOK(int termc)
67 {
68 int skip_white = (termc == ' ');
69 char *cp = buf;
70 int c;
71
72 while ((c = getchar()) != EOF) {
73 if (skip_white && isspace(c))
74 continue;
75 skip_white = 0;
76 if (c == '\n' && isspace(termc))
77 c = termc; /* forgiving assumption */
78 *cp++ = c;
79 if (cp-buf >= sizeof(buf))
80 break;
81 if ((termc == ' ') ? isspace(c) : (c == termc)) {
82 *cp = '\0';
83 return(cp-buf);
84 }
85 }
86 return(0);
87 }
88
89
90 int
91 main(int argc, char *argv[])
92 {
93 int inpflags = 0;
94 int needres = 0;
95 int force = 0;
96 int append = 0;
97 long outcnt = 0;
98 int bininp = 0;
99 int nstdoutcomp = 0;
100 int curterm = '\n';
101 int curncomp = 1;
102 int curbytes = 0;
103 int curflags = 0;
104 const char *curfmt = "ascii";
105 int i;
106
107 for (i = 1; i < argc; i++) {
108 if (argv[i][0] == '-') {
109 switch (argv[i][1]) {
110 case 't':
111 curterm = argv[i][2];
112 if (!curterm) curterm = '\n';
113 break;
114 case 'i':
115 switch (argv[i][2]) {
116 case 'h':
117 inpflags ^= DOHEADER;
118 break;
119 case 'H':
120 inpflags ^= DORESOLU;
121 break;
122 default:
123 goto badopt;
124 }
125 break;
126 case 'f':
127 force = !force;
128 break;
129 case 'a':
130 append = !append;
131 break;
132 case 'x':
133 ourres.xr = atoi(argv[++i]);
134 break;
135 case 'y':
136 ourres.yr = atoi(argv[++i]);
137 break;
138 case 'o':
139 switch (argv[i][2]) {
140 case 'n':
141 outcnt = atol(argv[++i]);
142 continue;
143 case 'h':
144 curflags ^= DOHEADER;
145 continue;
146 case 'H':
147 curflags ^= DORESOLU;
148 continue;
149 case 'f':
150 curfmt = "float";
151 curbytes = sizeof(float);
152 break;
153 case 'd':
154 curfmt = "double";
155 curbytes = sizeof(double);
156 break;
157 case 'i':
158 curfmt = "int";
159 curbytes = sizeof(int);
160 break;
161 case 'w':
162 curfmt = "16-bit";
163 curbytes = 2;
164 break;
165 case 'b':
166 curfmt = "byte";
167 curbytes = 1;
168 break;
169 case 'a':
170 curfmt = "ascii";
171 curbytes = 0;
172 break;
173 default:
174 goto badopt;
175 }
176 curncomp = isdigit(argv[i][3]) ?
177 atoi(argv[i]+3) : 1 ;
178 if (curbytes*curncomp > (int)sizeof(buf)) {
179 fputs(argv[0], stderr);
180 fputs(": output size too big\n", stderr);
181 return(1);
182 }
183 bininp += (curbytes > 0);
184 break;
185 case '\0': /* stdout */
186 if (!nstdoutcomp) { /* first use? */
187 needres |= (curflags & DORESOLU);
188 hdrflags[nfiles] = curflags;
189 }
190 output[nfiles] = stdout;
191 if (curbytes > 0)
192 SET_FILE_BINARY(output[nfiles]);
193 termc[nfiles] = curterm;
194 format[nfiles] = curfmt;
195 nstdoutcomp +=
196 ncomp[nfiles] = curncomp;
197 bytsiz[nfiles++] = curbytes;
198 break;
199 badopt:;
200 default:
201 fputs(argv[0], stderr);
202 fputs(": bad option\n", stderr);
203 return(1);
204 }
205 } else if (argv[i][0] == '.' && !argv[i][1]) {
206 output[nfiles] = NULL; /* discard data */
207 termc[nfiles] = curterm;
208 format[nfiles] = curfmt;
209 ncomp[nfiles] = curncomp;
210 bytsiz[nfiles++] = curbytes;
211 } else if (argv[i][0] == '!') {
212 needres |= (curflags & DORESOLU);
213 hdrflags[nfiles] = curflags;
214 termc[nfiles] = curterm;
215 if ((output[nfiles] = popen(argv[i]+1, "w")) == NULL) {
216 fputs(argv[i], stderr);
217 fputs(": cannot start command\n", stderr);
218 return(1);
219 }
220 if (curbytes > 0)
221 SET_FILE_BINARY(output[nfiles]);
222 format[nfiles] = curfmt;
223 ncomp[nfiles] = curncomp;
224 bytsiz[nfiles++] = curbytes;
225 } else {
226 if (append & (curflags != 0)) {
227 fputs(argv[0], stderr);
228 fputs(": -a option incompatible with -oh and -oH\n",
229 stderr);
230 return(1);
231 }
232 needres |= (curflags & DORESOLU);
233 hdrflags[nfiles] = curflags;
234 termc[nfiles] = curterm;
235 if (!append & !force && access(argv[i], F_OK) == 0) {
236 fputs(argv[i], stderr);
237 fputs(": file exists -- use -f to overwrite\n",
238 stderr);
239 return(1);
240 }
241 output[nfiles] = fopen(argv[i], append ? "a" : "w");
242 if (output[nfiles] == NULL) {
243 fputs(argv[i], stderr);
244 fputs(": cannot open for output\n", stderr);
245 return(1);
246 }
247 if (curbytes > 0)
248 SET_FILE_BINARY(output[nfiles]);
249 format[nfiles] = curfmt;
250 ncomp[nfiles] = curncomp;
251 bytsiz[nfiles++] = curbytes;
252 }
253 if (nfiles >= MAXFILE) {
254 fputs(argv[0], stderr);
255 fputs(": too many output streams\n", stderr);
256 return(1);
257 }
258 }
259 if (!nfiles) {
260 fputs(argv[0], stderr);
261 fputs(": no output streams\n", stderr);
262 return(1);
263 }
264 if (bininp) /* binary input? */
265 SET_FILE_BINARY(stdin);
266 #ifdef getc_unlocked /* avoid lock/unlock overhead */
267 flockfile(stdin);
268 for (i = nfiles; i--; )
269 if (output[i] != NULL)
270 ftrylockfile(output[i]);
271 #endif
272 /* load/copy header */
273 if (inpflags & DOHEADER && getheader(stdin, headline, NULL) < 0) {
274 fputs(argv[0], stderr);
275 fputs(": cannot read header from standard input\n",
276 stderr);
277 return(1);
278 }
279 /* handle resolution string */
280 if (inpflags & DORESOLU && !fgetsresolu(&ourres, stdin)) {
281 fputs(argv[0], stderr);
282 fputs(": bad resolution string on standard input\n", stderr);
283 return(1);
284 }
285 if (needres && (ourres.xr <= 0) | (ourres.yr <= 0)) {
286 fputs(argv[0], stderr);
287 fputs(": -oH option requires -iH or -x and -y options\n", stderr);
288 return(1);
289 }
290 if ((ourres.xr > 0) & (ourres.yr > 0)) {
291 if (outcnt <= 0) {
292 outcnt = ourres.xr * ourres.yr;
293 } else if (outcnt != ourres.xr*ourres.yr) {
294 fputs(argv[0], stderr);
295 fputs(": warning: -on option does not agree with resolution\n",
296 stderr);
297 }
298 }
299 for (i = 0; i < nfiles; i++) { /* complete headers */
300 if (hdrflags[i] & DOHEADER) {
301 if (!(inpflags & DOHEADER))
302 newheader("RADIANCE", output[i]);
303 printargs(argc, argv, output[i]);
304 fprintf(output[i], "NCOMP=%d\n", output[i]==stdout ?
305 nstdoutcomp : ncomp[i]);
306 if (format[i] != NULL) {
307 extern const char BIGEND[];
308 if (format[i][0] != 'a') {
309 fputs(BIGEND, output[i]);
310 fputs(nativebigendian() ^ swapped ?
311 "1\n" : "0\n", output[i]);
312 }
313 fputformat(format[i], output[i]);
314 }
315 fputc('\n', output[i]);
316 }
317 if (hdrflags[i] & DORESOLU)
318 fputsresolu(&ourres, output[i]);
319 }
320 do { /* main loop */
321 for (i = 0; i < nfiles; i++) {
322 if (bytsiz[i] > 0) { /* binary output */
323 if (getbinary(buf, bytsiz[i], ncomp[i],
324 stdin) < ncomp[i])
325 break;
326 if (output[i] != NULL &&
327 putbinary(buf, bytsiz[i], ncomp[i],
328 output[i]) < ncomp[i])
329 break;
330 } else if (ncomp[i] > 1) { /* N-field output */
331 int n = ncomp[i];
332 while (n--) {
333 if (!scanOK(termc[i]))
334 break;
335 if (output[i] != NULL &&
336 fputs(buf, output[i]) == EOF)
337 break;
338 }
339 if (n >= 0) /* fell short? */
340 break;
341 if ((output[i] != NULL) & /* add EOL if none */
342 (termc[i] != '\n'))
343 fputc('\n', output[i]);
344 } else { /* 1-field output */
345 if (!scanOK(termc[i]))
346 break;
347 if (output[i] != NULL) {
348 if (fputs(buf, output[i]) == EOF)
349 break;
350 if (termc[i] != '\n') /* add EOL? */
351 fputc('\n', output[i]);
352 }
353 }
354 /* skip input EOL? */
355 if (!bininp && termc[nfiles-1] != '\n') {
356 int c = getchar();
357 if ((c != '\n') & (c != EOF))
358 ungetc(c, stdin);
359 }
360 }
361 if (i < nfiles)
362 break;
363 } while (--outcnt);
364 /* check ending */
365 if (fflush(NULL) == EOF) {
366 fputs(argv[0], stderr);
367 fputs(": write error on one or more outputs\n", stderr);
368 return(1);
369 }
370 if (outcnt > 0) {
371 fputs(argv[0], stderr);
372 fputs(": warning: premature EOD\n", stderr);
373 }
374 return(0);
375 }