ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.13
Committed: Sat Apr 4 16:23:00 2020 UTC (4 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.12: +21 -9 lines
Log Message:
Added '.' for discarding output

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rsplit.c,v 1.12 2020/03/31 16:39:01 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 curterm = '\n';
100 int curncomp = 1;
101 int curbytes = 0;
102 int curflags = 0;
103 const char *curfmt = "ascii";
104 int i;
105
106 for (i = 1; i < argc; i++) {
107 if (argv[i][0] == '-') {
108 switch (argv[i][1]) {
109 case 't':
110 curterm = argv[i][2];
111 if (!curterm) curterm = '\n';
112 break;
113 case 'i':
114 switch (argv[i][2]) {
115 case 'h':
116 inpflags ^= DOHEADER;
117 break;
118 case 'H':
119 inpflags ^= DORESOLU;
120 break;
121 default:
122 goto badopt;
123 }
124 break;
125 case 'f':
126 force = !force;
127 break;
128 case 'a':
129 append = !append;
130 break;
131 case 'x':
132 ourres.xr = atoi(argv[++i]);
133 break;
134 case 'y':
135 ourres.yr = atoi(argv[++i]);
136 break;
137 case 'o':
138 switch (argv[i][2]) {
139 case 'n':
140 outcnt = atol(argv[++i]);
141 continue;
142 case 'h':
143 curflags ^= DOHEADER;
144 continue;
145 case 'H':
146 curflags ^= DORESOLU;
147 continue;
148 case 'f':
149 curfmt = "float";
150 curbytes = sizeof(float);
151 break;
152 case 'd':
153 curfmt = "double";
154 curbytes = sizeof(double);
155 break;
156 case 'i':
157 curfmt = "int";
158 curbytes = sizeof(int);
159 break;
160 case 'w':
161 curfmt = "16-bit";
162 curbytes = 2;
163 break;
164 case 'b':
165 curfmt = "byte";
166 curbytes = 1;
167 break;
168 case 'a':
169 curfmt = "ascii";
170 curbytes = 0;
171 break;
172 default:
173 goto badopt;
174 }
175 curncomp = isdigit(argv[i][3]) ?
176 atoi(argv[i]+3) : 1 ;
177 if (curbytes*curncomp > (int)sizeof(buf)) {
178 fputs(argv[0], stderr);
179 fputs(": output size too big\n", stderr);
180 return(1);
181 }
182 bininp += (curbytes > 0);
183 break;
184 case '\0':
185 needres |= (curflags & DORESOLU);
186 termc[nfiles] = curterm;
187 hdrflags[nfiles] = curflags;
188 output[nfiles] = stdout;
189 if (curbytes > 0)
190 SET_FILE_BINARY(output[nfiles]);
191 format[nfiles] = curfmt;
192 ncomp[nfiles] = curncomp;
193 bytsiz[nfiles++] = curbytes;
194 break;
195 badopt:;
196 default:
197 fputs(argv[0], stderr);
198 fputs(": bad option\n", stderr);
199 return(1);
200 }
201 } else if (argv[i][0] == '.' && !argv[i][1]) {
202 output[nfiles] = NULL; /* discard data */
203 termc[nfiles] = curterm;
204 format[nfiles] = curfmt;
205 ncomp[nfiles] = curncomp;
206 bytsiz[nfiles++] = curbytes;
207 } else if (argv[i][0] == '!') {
208 needres |= (curflags & DORESOLU);
209 termc[nfiles] = curterm;
210 hdrflags[nfiles] = curflags;
211 if ((output[nfiles] = popen(argv[i]+1, "w")) == NULL) {
212 fputs(argv[i], stderr);
213 fputs(": cannot start command\n", stderr);
214 return(1);
215 }
216 if (curbytes > 0)
217 SET_FILE_BINARY(output[nfiles]);
218 format[nfiles] = curfmt;
219 ncomp[nfiles] = curncomp;
220 bytsiz[nfiles++] = curbytes;
221 } else {
222 if (append & (curflags != 0)) {
223 fputs(argv[0], stderr);
224 fputs(": -a option incompatible with -oh and -oH\n",
225 stderr);
226 return(1);
227 }
228 needres |= (curflags & DORESOLU);
229 termc[nfiles] = curterm;
230 hdrflags[nfiles] = curflags;
231 if (!append & !force && access(argv[i], F_OK) == 0) {
232 fputs(argv[i], stderr);
233 fputs(": file exists -- use -f to overwrite\n",
234 stderr);
235 return(1);
236 }
237 output[nfiles] = fopen(argv[i], append ? "a" : "w");
238 if (output[nfiles] == NULL) {
239 fputs(argv[i], stderr);
240 fputs(": cannot open for output\n", stderr);
241 return(1);
242 }
243 if (curbytes > 0)
244 SET_FILE_BINARY(output[nfiles]);
245 format[nfiles] = curfmt;
246 ncomp[nfiles] = curncomp;
247 bytsiz[nfiles++] = curbytes;
248 }
249 if (nfiles >= MAXFILE) {
250 fputs(argv[0], stderr);
251 fputs(": too many output streams\n", stderr);
252 return(1);
253 }
254 }
255 if (!nfiles) {
256 fputs(argv[0], stderr);
257 fputs(": no output streams\n", stderr);
258 return(1);
259 }
260 if (bininp) /* binary input? */
261 SET_FILE_BINARY(stdin);
262 #ifdef getc_unlocked /* avoid lock/unlock overhead */
263 flockfile(stdin);
264 for (i = nfiles; i--; )
265 if (output[i] != NULL)
266 flockfile(output[i]);
267 #endif
268 /* load/copy header */
269 if (inpflags & DOHEADER && getheader(stdin, headline, NULL) < 0) {
270 fputs(argv[0], stderr);
271 fputs(": cannot get header from standard input\n",
272 stderr);
273 return(1);
274 }
275 /* handle resolution string */
276 if (inpflags & DORESOLU && !fgetsresolu(&ourres, stdin)) {
277 fputs(argv[0], stderr);
278 fputs(": cannot get resolution string from standard input\n",
279 stderr);
280 return(1);
281 }
282 if (needres && (ourres.xr <= 0) | (ourres.yr <= 0)) {
283 fputs(argv[0], stderr);
284 fputs(": -oH option requires -iH or -x and -y options\n", stderr);
285 return(1);
286 }
287 if ((ourres.xr > 0) & (ourres.yr > 0)) {
288 if (outcnt <= 0) {
289 outcnt = ourres.xr * ourres.yr;
290 } else if (outcnt != ourres.xr*ourres.yr) {
291 fputs(argv[0], stderr);
292 fputs(": warning: -on option does not agree with resolution\n",
293 stderr);
294 }
295 }
296 for (i = 0; i < nfiles; i++) { /* complete headers */
297 if (hdrflags[i] & DOHEADER) {
298 if (!(inpflags & DOHEADER))
299 newheader("RADIANCE", output[i]);
300 printargs(argc, argv, output[i]);
301 fprintf(output[i], "NCOMP=%d\n", ncomp[i]);
302 if (format[i] != NULL) {
303 extern const char BIGEND[];
304 if ((format[i][0] == 'f') |
305 (format[i][0] == 'd')) {
306 fputs(BIGEND, output[i]);
307 fputs(nativebigendian() ^ swapped ?
308 "1\n" : "0\n", output[i]);
309 }
310 fputformat(format[i], output[i]);
311 }
312 fputc('\n', output[i]);
313 }
314 if (hdrflags[i] & DORESOLU)
315 fputsresolu(&ourres, output[i]);
316 }
317 do { /* main loop */
318 for (i = 0; i < nfiles; i++) {
319 if (bytsiz[i] > 0) { /* binary output */
320 if (getbinary(buf, bytsiz[i], ncomp[i],
321 stdin) < ncomp[i])
322 break;
323 if (output[i] != NULL &&
324 putbinary(buf, bytsiz[i], ncomp[i],
325 output[i]) < ncomp[i])
326 break;
327 } else if (ncomp[i] > 1) { /* N-field output */
328 int n = ncomp[i];
329 while (n--) {
330 if (!scanOK(termc[i]))
331 break;
332 if (output[i] != NULL &&
333 fputs(buf, output[i]) == EOF)
334 break;
335 }
336 if (n >= 0) /* fell short? */
337 break;
338 if ((output[i] != NULL) & /* add EOL if none */
339 (termc[i] != '\n'))
340 fputc('\n', output[i]);
341 } else { /* 1-field output */
342 if (!scanOK(termc[i]))
343 break;
344 if (output[i] != NULL) {
345 if (fputs(buf, output[i]) == EOF)
346 break;
347 if (termc[i] != '\n') /* add EOL? */
348 fputc('\n', output[i]);
349 }
350 }
351 /* skip input EOL? */
352 if (!bininp && termc[nfiles-1] != '\n') {
353 int c = getchar();
354 if ((c != '\n') & (c != EOF))
355 ungetc(c, stdin);
356 }
357 }
358 if (i < nfiles)
359 break;
360 } while (--outcnt);
361 /* check ending */
362 if (fflush(NULL) == EOF) {
363 fputs(argv[0], stderr);
364 fputs(": write error on one or more outputs\n", stderr);
365 return(1);
366 }
367 if (outcnt > 0) {
368 fputs(argv[0], stderr);
369 fputs(": warning: premature EOD\n", stderr);
370 }
371 return(0);
372 }