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

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 1.8 static const char RCSid[] = "$Id: rsplit.c,v 1.7 2019/07/20 23:12:53 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 <ctype.h>
12    
13 greg 1.6 #include "rtio.h"
14 greg 1.1 #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 greg 1.7 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 greg 1.1
29 greg 1.7 static RESOLU ourres = {PIXSTANDARD, 0, 0};
30 greg 1.1
31 greg 1.7 static char buf[16384]; /* input buffer used in scanOK() */
32 greg 1.1
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 greg 1.8 int inpflags = 0;
80     int needres = 0;
81 greg 1.1 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 greg 1.5 if (!curterm) curterm = '\n';
97 greg 1.1 break;
98     case 'i':
99     switch (argv[i][2]) {
100     case 'h':
101 greg 1.8 inpflags ^= DOHEADER;
102 greg 1.1 break;
103     case 'H':
104 greg 1.8 inpflags ^= DORESOLU;
105 greg 1.1 break;
106     default:
107     goto badopt;
108     }
109     break;
110     case 'f':
111 greg 1.8 force = !force;
112 greg 1.1 break;
113     case 'a':
114 greg 1.8 append = !append;
115 greg 1.1 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 greg 1.7 curbytes = -1;
156 greg 1.1 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 greg 1.7 bininp += (curbytes > 0);
169 greg 1.1 break;
170     case '\0':
171 greg 1.8 needres |= (curflags & DORESOLU);
172 greg 1.1 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 greg 1.8 needres |= (curflags & DORESOLU);
188 greg 1.1 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 greg 1.8 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 greg 1.1 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 greg 1.8 if (inpflags & DOHEADER && getheader(stdin, headline, NULL) < 0) {
246 greg 1.1 fputs(argv[0], stderr);
247     fputs(": cannot get header from standard input\n",
248     stderr);
249     return(1);
250     }
251     /* handle resolution string */
252 greg 1.8 if (inpflags & DORESOLU && !fgetsresolu(&ourres, stdin)) {
253 greg 1.1 fputs(argv[0], stderr);
254     fputs(": cannot get resolution string from standard input\n",
255     stderr);
256     return(1);
257     }
258 greg 1.8 if (needres && (ourres.xr <= 0) | (ourres.yr <= 0)) {
259 greg 1.1 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 greg 1.8 if (!(inpflags & DOHEADER))
275 greg 1.1 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 greg 1.7 if (putbinary(buf, bytsiz[i], 1, output[i]) < 1)
290 greg 1.4 break;
291 greg 1.1 } else if (bytsiz[i] < 0) { /* N-field output */
292     int n = -bytsiz[i];
293     while (n--) {
294     if (!scanOK(termc[i]))
295     break;
296 greg 1.4 if (fputs(buf, output[i]) == EOF)
297     break;
298 greg 1.1 }
299     if (n >= 0) /* fell short? */
300     break;
301 greg 1.4 if (termc[i] != '\n') /* add EOL if none */
302     fputc('\n', output[i]);
303 greg 1.1 } else { /* 1-field output */
304     if (!scanOK(termc[i]))
305     break;
306 greg 1.4 if (fputs(buf, output[i]) == EOF)
307     break;
308     if (termc[i] != '\n') /* add EOL if none */
309     fputc('\n', output[i]);
310 greg 1.1 }
311 greg 1.7 /* 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 greg 1.1 }
318     if (i < nfiles)
319     break;
320     } while (--outcnt);
321 greg 1.2 /* check ending */
322 greg 1.3 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 greg 1.4 if (outcnt > 0) {
328     fputs(argv[0], stderr);
329     fputs(": warning: premature EOD\n", stderr);
330     }
331 greg 1.1 return(0);
332     }