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

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 1.3 static const char RCSid[] = "$Id: rsplit.c,v 1.2 2019/07/05 00:46:23 greg Exp $";
3 greg 1.1 #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 greg 1.2 /* check ending */
319     if (outcnt > 0) {
320     fputs(argv[0], stderr);
321     fputs(": warning: premature EOD\n", stderr);
322     }
323 greg 1.3 if (fflush(NULL) == EOF) {
324     fputs(argv[0], stderr);
325     fputs(": write error on one or more outputs\n", stderr);
326     return(1);
327     }
328 greg 1.1 return(0);
329     }