ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.11
Committed: Thu Nov 7 23:13:12 2019 UTC (4 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.10: +8 -2 lines
Log Message:
Made it so a space separator matches all white space

File Contents

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