ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.7
Committed: Sat Jul 20 23:12:53 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +19 -16 lines
Log Message:
Fixed issue with extra newline

File Contents

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