ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.8
Committed: Mon Jul 22 18:01:03 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +20 -26 lines
Log Message:
Made option behavior more consistent

File Contents

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