ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.2
Committed: Fri Jul 5 00:46:23 2019 UTC (4 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +6 -1 lines
Log Message:
Added check for premature end-of-data

File Contents

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